33

UI を表示するフラグメントの設定.setOnRetainInstance(true)がメモリ リークにつながる可能性があることを読みました。

誰かがなぜ、どのようにこれが起こるのか説明してもらえますか? 詳細な説明はどこにもありませんでした。

4

5 に答える 5

96

with UIでは、いくつかの をインスタンス状態としてFragment保存して、アクセスを高速化することがよくあります。Viewたとえば、あなたへのリンクなEditTextので、常にアクセスする必要はありませんfindViewById

問題は、 aがコンテキストViewへの参照を保持していることです。Activity保持するViewと、そのコンテキストへの参照も保持されます。

コンテキストがまだ有効である場合は問題ありませんが、典型的な保持ケースはアクティビティの再起動です。たとえば、画面の回転などで非常に頻繁に使用されます。アクティビティの再作成は新しいコンテキストを作成し、古いコンテキストはガベージ コレクションを目的としています。Fragmentただし、古いものへの参照がまだ残っているため、ガベージコレクションを実行することはできません。

次の例は、それを行わない方法を示しています

public class LeakyFragment extends Fragment {

    private View mLeak; // retained

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mLeak = inflater.inflate(R.layout.whatever, container, false);
        return mLeak;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        // not cleaning up.
    }
}

この問題を解決するには、UI へのすべての参照を でクリアする必要がありますonDestroyViewFragmentインスタンスが再利用されると、 で新しい UI を作成するよう求められますonCreateView。の後にUIを保持しても意味がありませんonDestroyView。Ui は使用しません。

この例の修正は、次のように変更onDestroyViewするだけです

@Override
public void onDestroyView() {
    super.onDestroyView();
    mLeak = null; // now cleaning up!
}

また、 s への参照を保持する以外に、 (たとえば from - clean on ) または(コンテキストでない限り)Viewへの参照を保持しないことは明らかです。ActivityonAttachonDetachContextApplication

于 2012-11-16T19:06:14.853 に答える
3

アクティビティに結合されている特定のオブジェクトを保持する場合は注意してください。

注意:任意のオブジェクトを返すことができますが、 Activity に関連付けられているオブジェクト ( DrawableAdapterView、または Context に関連付けられているその他のオブジェクトなど) を渡さないでください。これを行うと、元のアクティビティ インスタンスのすべてのビューとリソースがリークします。(リソースのリークは、アプリケーションがリソースを保持し続け、それらをガベージ コレクションできないことを意味するため、大量のメモリが失われる可能性があります。)

http://developer.android.com/guide/topics/resources/runtime-changes.html#RetainingAnObject

于 2013-05-03T16:24:43.697 に答える
3

setRetainInstance(true)画面の回転やその他の構成の変更など、アクティビティの再作成中に動的フラグメントのインスタンスを保持するために使用されます。ただし、これは Fragment がシステムによって永久に保持されるという意味ではありません。

ユーザーがアクティビティを終了する (押し戻す) など、他の理由でアクティビティが終了した場合、フラグメントはガベージ コレクションの対象となる必要があります。

于 2012-11-16T18:03:23.090 に答える
-11

onDestroy() ガベージ コレクターをオーバーライドして呼び出すことができます。

 @Override
public void onDestroy() {
    super.onDestroy();
    System.gc();
    System.gc();
}
于 2016-04-14T09:18:33.590 に答える