web-dev-qa-db-ja.com

フラグメントが置き換えられ、バックスタックに入れられた(または削除された)とき、それはメモリに残りますか?

動作はアクティビティの動作に似ていますか?たとえば、アクティビティの場合、次のように機能します。

アクティビティA開始アクティビティB[〜#〜] b [〜#〜]は画面上にあり、システムは削除できます- [〜#〜] a [〜#〜]システムで必要な場合はメモリから。 BACKを押すと、[〜#〜] a [〜#〜]が最初の場所に残らないかのようにメモリに再作成されます。

私はFragmentsで記憶に関して賢明なことが起こることの明確な説明を探しましたが、何も見つけていません。同じように機能しますか?例えば:

アクティビティCには、レイアウトにフラグメントFがあります。次に、ある時点で[〜#〜] f [〜#〜]Fragment Gに置き換えられますが、[〜#〜] f [〜# 〜]はそのバックスタックに保持されます。

ウィル[〜#〜] f [〜#〜][〜#〜] c [〜#〜]が削除されるか、削除されるまでメモリにとどまります必要に応じてシステム?

私が尋ねているのは、単一のアクティビティに複雑なフラグメントのバックスタックがある場合、メモリ不足のリスクを負うかどうかです?

71
cottonBallPaws

これを見てください: BackStackRecord.Op.fragment

これが、フラグメントがバックスタックに格納される方法です。ライブ参照に注意してください。WeakReferenceSoftReferenceも使用されていません。

これは次のとおりです。 FragmentManagerImpl.mBackStack

マネージャがバックスタックを保存する場所です。単純なArrayListも、WRまたはSRはありません。

そして最後に: Activity.mFragments

これがフラグメントマネージャーへの参照です。

GCは、ライブ参照を持たない(スレッドから到達できない)オブジェクトのみを収集できます。つまり、アクティビティが破棄されるまで(したがって、FragmentManager参照がなくなった)、 GCは、バックスタック内のフラグメントを収集できません

Activityが破棄され、 状態を保持 (デバイスをランドスケープモードに切り替えたときなど)の場合、スタック内の実際のFragmentオブジェクトは保持されず、状態のみが保持されることに注意してください-- Fragment.FragmentState オブジェクト、つまり、バックスタック内の実際のフラグメントは、アクティビティが保持状態で再作成されるたびに再作成されます。

お役に立てれば。

[〜#〜] ps [〜#〜]つまり、要するに:はい、Fragmentsをバックスタックに追加し、ビュー階層を表示するにはビューを追加しすぎます。

[〜#〜] upd [〜#〜]あなたの例を考えると、[〜#〜] f [〜#〜]は、[〜#〜] c [〜#〜]が強制終了されるまでメモリに残ります。 [〜#〜] c [〜#〜]が強制終了され、異なる構成で復活した場合-[〜 #〜] f [〜#〜]も破棄され、別のオブジェクトに生まれ変わります。したがって、[〜#〜] f [〜#〜]のメモリフットプリントは、[〜#まで〜] c [〜#〜]は状態を失うか、バックスタックがクリアされます。

101
Ivan Bartsov

公式の情報源を提供できなかったことを残念に思いますが、何が起こるかを知りたいと思い、それをテストすることにしました。そして、私のテストによると、はい、あなたはメモリ不足のリスクを冒しています。

OutOfMemoryErrorが発生するために、forループに信じられないほどの数(100以上)のフラグメントを追加する必要がありましたが、実際に発生しました。ログを確認すると、onCreate()メソッドとonCreateView()メソッドが何度も呼び出されていることがわかりましたが、onSaveInstance()onPause()onDestroyまったく呼び出されませんでした。

参考までに、フラグメントをバックスタックに追加する方法は次のとおりです。

_getSupportFragmentManager().beginTransaction().add(R.id.scene_fragment_container, mSceneFragment).addToBackStack("FOOBAR").commit();
_

そして、私が追加したフラグメントはやや単純でした:ImageViewEditText、カップルTextViewsSeekBarListView

ただし、メモリに大量のデータを保持している場合を除き、問題になることはありません。

その後、バックスタックに50個だけ追加して、アプリを強制終了して再起動しようとしました。そして、私が望んだ/推測したように、すべてのフラグメントが復元された(そしてonSaveInstance()onPause()メソッドが呼び出された)ので、私のライフサイクル実装はOutOfMemoryErrorを引き起こす問題ではなかった。

7

Developer.Android.com/guide/topics/fundamentals/fragments.htmlから

フラグメントは常にアクティビティに埋め込む必要があり、フラグメントのライフサイクルはホストアクティビティのライフサイクルの影響を直接受けます。たとえば、アクティビティが一時停止すると、その中のすべてのフラグメントも停止し、アクティビティが破棄されると、すべてのフラグメントも停止します。ただし、アクティビティの実行中(ライフサイクルが再開された状態)、各フラグメントを追加または削除するなど、個別に操作できます。このようなフラグメントトランザクションを実行する場合、アクティビティによって管理されるバックスタックに追加することもできます。アクティビティ内の各バックスタックエントリは、発生したフラグメントトランザクションの記録です。バックスタックを使用すると、ユーザーは[戻る]ボタンを押すことで、フラグメントトランザクションを逆にする(逆方向にナビゲートする)ことができます。

4
Bill Gary

はい、1つのアクティビティで大量のフラグメントを作成するとメモリ不足になる可能性があります。フラグメントは、含まれているアクティビティが破棄されたときにのみ破棄されます。

1
Sid