当片段被替换并放入后栈(或删除)时,它是否留在内存中?

cot*_*aws 71 memory android view android-fragments android-activity

行为是否类似于活动的工作方式?例如,使用Activities,它的工作原理如下:

活动A启动活动B,而B在屏幕上,如果系统需要,系统可以从内存中删除A. 按下BACK后,A将重新创建到内存中,就像它从未离开过一样.

我已经找到了一个明确的解释,说明片段内存发生了什么,并没有发现任何东西.它的工作方式是否相同?例如:

活动C的布局中包含片段F. 然后,在某些时候F片段G替换,但F保持在其后栈中.

F会在C被杀之前留在内存中还是可以根据需要由系统删除?

真的我要问的是,如果我在一个Activity中有一堆复杂的碎片,我是否会冒内存不足的风险?

Iva*_*sov 101

看看这个:BackStackRecord.Op.fragment

这就是片段存储在后栈中的方式.注意实时参考,既不WeakReference也没有SoftReference在那里使用.

现在这个:FragmentManagerImpl.mBackStack

这就是经理存储后台的地方.简单ArrayList,也没有WR或SR.

最后这个:Activity.mFragments

这是对片段管理器的引用.

GC只能收集没有实时引用的对象(无法从任何线程访问).这意味着,直到您的Activity被销毁(因此,FragmentManager引用已经消失),GC将无法收集后端堆栈中的任何片段.

请注意,当Activity被销毁并保持状态时(比如将设备转换为横向模式),它不会保留Fragment堆栈中的实际对象,只会保留其状态 - Fragment.FragmentState对象,即后堆栈中的实际片段每次使用保留状态重新创建活动时创建.

希望这可以帮助.

PS因此,简而言之:是的,您可以通过添加Fragments到后台堆栈以及添加太多视图来查看层次结构来耗尽内存.

UPD考虑到你的例子,F将留在内存中直到C被杀死.如果C被杀死然后以不同的配置复活 - F也将被销毁并在另一个对象中重生.因此,F的内存占用率一直存在,直到C丢失状态或后备栈被清除.

  • 但请注意,当片段放在后栈上时,会调用其onDestroyView().如果此时您清理了片段所持有的任何主要分配,则不应该有内存问题. (30认同)
  • @traninho好主意.当放回到堆栈时,`Fragment`实例不会被破坏,因此`onDestroyView()`应该始终为null它所具有的任何视图引用.否则它将使死视图不被GCed.此外,即使重新创建了"活动",非反向堆栈保留的片段(参见`setRetainInstance(true)`)也不会被破坏,因此通过保持视图引用,您可以泄漏整个"活动".通常这不会发生,因为在99%的情况下,视图refs在`onCreateView()`中更新,它在Actvity娱乐中被调用,所以在此之后refs指向新的视图. (3认同)

Beo*_*son 7

我很抱歉无法向您提供一些官方信息来源,但我很好奇,看看会发生什么,并决定测试它.根据我的测试,是的,你冒着内存不足的风险.

我必须在for循环中添加一些令人难以置信的碎片(超过一百个)OutOfMemoryError,但它确实发生了.和检查我的日志,我可以看到onCreate()onCreateView()方法,被称为很多次了,但是onSaveInstance(),onPause()onDestroy所有不叫.

作为参考,这是我将片段添加到backstack的方式:

getSupportFragmentManager().beginTransaction().add(R.id.scene_fragment_container, mSceneFragment).addToBackStack("FOOBAR").commit();
Run Code Online (Sandbox Code Playgroud)

我添加的片段有点简单:a ImageView,an EditText,a couple TextViews,a SeekBar和a ListView.

但除非你在内存中存储大量数据,否则它应该不是问题.

后来我尝试只在后台堆栈中添加50,杀死应用程序并重新启动它.正如我希望/猜测,所有的片段被恢复(和onSaveInstance()onPause()方法调用),所以我的生命周期实现并不导致该问题的OutOfMemoryError火.