我已经读过.setOnRetainInstance(true)
在呈现 UI 的片段上的设置可能会导致内存泄漏。
有人可以解释为什么以及如何发生这种情况吗?我在任何地方都没有找到详细的解释。
我已经读过.setOnRetainInstance(true)
在呈现 UI 的片段上的设置可能会导致内存泄漏。
有人可以解释为什么以及如何发生这种情况吗?我在任何地方都没有找到详细的解释。
在Fragment
with UI 中,您经常将一些View
s 保存为实例状态以加快访问速度。例如指向您的链接,EditText
这样您就不必一直访问findViewById
它。
问题是 aView
保持对Activity
上下文的引用。现在,如果您保留 aView
您还保留对该上下文的引用。
如果上下文仍然有效但典型的保留情况是重新启动 Activity,那没问题。例如,经常用于屏幕旋转。活动重新创建将创建一个新的上下文,而旧的上下文将被垃圾收集。但它现在不能被垃圾收集,因为你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 的引用onDestroyView
。一旦Fragment
实例被重用,您将被要求在onCreateView
. 将 UI 保留在onDestroyView
. Ui 不会被使用。
此示例中的修复只是更改onDestroyView
为
@Override
public void onDestroyView() {
super.onDestroyView();
mLeak = null; // now cleaning up!
}
除了保留对View
s 的引用之外,您显然不应该保留对Activity
(例如 from onAttach
- clean on onDetach
)或任何Context
(除非它是Application
上下文)的引用。
setRetainInstance(true)
用于在 Activity 重新创建期间保留动态片段的实例,例如屏幕旋转或其他配置更改。但这并不意味着 Fragment 将被系统永远保留。
当 Activity 因其他原因终止时,例如用户完成 Activity(即按回),Fragment 应该有资格进行垃圾回收。
保留与 Activity 耦合的某些对象时要小心。
注意:虽然您可以返回任何对象,但您绝不应该传递与 Activity 相关联的对象,例如Drawable、Adapter、View或与 Context 关联的任何其他对象。如果这样做,它将泄漏原始活动实例的所有视图和资源。(资源泄漏意味着您的应用程序会保留它们并且它们不能被垃圾收集,因此可能会丢失大量内存。)
http://developer.android.com/guide/topics/resources/runtime-changes.html#RetainingAnObject
“setRetainInstance”用于在重新创建活动时维护片段的状态。根据官方文档:如果我们使用“setRetainInstance”,片段生命周期的2个方法(onCreate,onDestroy)将不会被执行。但是,片段中包含的视图将被重新创建,这是因为生命周期将从“onCreateView”执行。在这些情况下,如果我们在“onSaveInstanceState”中保存了一些数据,我们应该在“onActivityCreated”而不是“onCreate”中请求它。
官方信息:https://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)
更多信息:https ://inthecheesefactory.com/blog/fragment-state-saving-best-practices/en
您可以覆盖onDestroy()
并调用垃圾收集器。
@Override
public void onDestroy() {
super.onDestroy();
System.gc();
System.gc();
}