6

匿名クラスは、特にAndroidの世界では、構成の変更によりアクティビティまたはフラグメントが突然破壊される可能性があるため、メモリリークを簡単に引き起こす可能性があります。これが多くの例の1つです。

http://chaosinmotion.com/blog/?p=696

http://blog.andresteingress.com/2011/10/12/anonymous-inner-classes-in-android/

https://blogs.oracle.com/olaf/entry/memory_leaks_made_easy

その理由は、またはで匿名クラスを作成するActivityFragment、匿名クラスは常にActivityまたはへの暗黙の参照を保持するためFragmentです。そのActivityため、構成の変更により機能しなくなる傾向がある場合、匿名クラスが外部に公開されて保持されていると、ガベージコレクションを行うことができません。

それで、データホルダー技術を使用することが、匿名クラスを完全に排除し、メモリリークのリスクを減らすための良い方法であるかどうか疑問に思いました。または、私は妄想を超えていますか?

匿名クラスの使用

public class HomeMenuFragment {
    private Parcelable selectedInfo = null;
    private List<View> homeMenuRows = new ArrayList<View>();

    private void fun() {
        ...
        ...
        row.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // homeMenuRows is member variable
                for (View r : homeMenuRows) {
                    r.setSelected(false);
                }
                row.setSelected(true);
                // selectedInfo is member variable
                selectedInfo = watchlistInfo;
            }
        });
    }
}

データホルダー手法を使用したリファクタリング

public class HomeMenuFragment {
    private static class Holder {
        public Parcelable selectedInfo = null;
        public final List<View> homeMenuRows = new ArrayList<View>();        
    }
    private final Holder holder = new Holder();

    private static class MyOnClickLisnter implements OnClickListener {
        private final Holder holder;
        private final LinearLayout row;
        private final WatchlistInfo watchlistInfo;

        public MyOnClickLisnter(Holder holder, LinearLayout row, WatchlistInfo watchlistInfo) {
            this.holder = holder;
            this.row = row;
            this.watchlistInfo = watchlistInfo;
        }

        @Override
        public void onClick(View arg0) {
            for (View r : holder.homeMenuRows) {
                r.setSelected(false);
            }
            row.setSelected(true);
            holder.selectedInfo = watchlistInfo;
        }        
    }

    private void fun() {
        ...
        ...
        row.setOnClickListener(new MyOnClickLisnter(holder, row, watchlistInfo));
    }
}
4

1 に答える 1

5

このようなリファクタリングは役に立ちません。内のViewオブジェクトHolderも への参照を保持するActivityため、Holderが外部に公開されていると、メモリ リークが発生します。また、あなたのMyOnClickLisnterインスタンスは、宣言されていても、とstaticへの明示的な参照を保持しています。どちらも への参照を保持しています。私は匿名クラスのファンではありませんが、匿名がorの外に渡される可能性は非常に小さいと思います。あなたは過度に妄想的であるように私には聞こえます。HolderLinearLayoutActivityOnClickListenerActivityFragment

于 2013-03-20T16:03:47.857 に答える