首页 > 解决方案 > 为什么必须在 onDestroyView() 中调用 clearFindViewByIdCache()?

问题描述

我试图了解 Kotlin Android 扩展,这篇文章说:

When asked for a view, it will try to find it in the cache. If it’s not there, it will find it and add it to the cache. Pretty simple indeed.

Besides, it adds a function to clear the cache: clearFindViewByIdCache. You can use it for instance if you have to rebuild the view, as the old views won't be valid anymore.

为什么在 onDestroy() 之后重建视图后旧视图不再有效?重建视图后,视图引用仍将存在,例如在 OnActivityCreated() 中。

标签: androidxmlkotlinkotlin-android-extensions

解决方案


这里重要的一点是,片段的生命周期通常比它们的视图更长。让我们考虑以下流程:

  1. 您创建Fragment A并将其放入容器中
  2. Fragment A视图已创建(此 onCreateView + onViewCreated)
  3. 您在容器中创建Fragment B并替换Fragment A为新片段 + 保留堆栈
  4. Fragment A此时视图将被销毁,但片段将保留在FragmentManager.
  5. back press和 Fragment B 被完全摧毁了,因为你合乎逻辑地离开了它。此时系统将其替换回来Fragment A并再次创建一个新视图。

所以这里有一些重要的注意事项:

在步骤#4,如果您保留任何指向子视图的链接,那么您的内存就会泄漏,因为所有这些都已经从您的视图层次结构中分离出来并且不能再使用了。基本上,您仍然将所有这些视图保存在内存中,即使它们不再使用。通常,人们不会注意到这一点,并且所有视图都会使用新的 onViewCreated(和findViewById)再次反弹,但是 kotlin 扩展将它们保存在缓存中并且基本上不会findViewById再次执行此操作,因此您可以获得旧的(读作死的)视图不是刚刚创建的那些视图。

例如,如果你现在使用 ButterKnife,他们也会在Binding Reset部分中对此进行描述。(http://jakewharton.github.io/butterknife/#reset)。

最后重要的一点是 Kotlin 扩展为您完成了这项工作,因此您实际上不需要在 onDestroyView 内部调用它,您只需使用它就可以了(就像魔术一样......)


推荐阅读