【问题标题】:onSaveInstanceState called after onDestroyViewonSaveInstanceState 在 onDestroyView 之后调用
【发布时间】:2018-05-14 18:05:01
【问题描述】:

我在这里处理奇怪的片段生命周期行为。

我有一个包含两个片段的活动:CityFragment - 显示城市列表和 WeatherFragment - 显示所选城市的天气预报。

当应用程序启动时,CityFragment 显示在屏幕上,当用户选择城市时 - WeatherFragment 通过 supportFragmentManager 与 backstack 添加。 然后,如果用户想旋转屏幕,我会得到图片上的情况

  • 0-2 -- CitiesFragment 启动
  • 3-7 -- 用户选择城市,WeatherFragment 显示在屏幕上
  • 8-18 -- 屏幕旋转

正如您在用户选择城市后立即在日志中看到的那样,为 CitiesFragment 调用 onStop 和 onDestroyView,之后的片段视图为空。 但是当屏幕旋转时,会调用 CitiesFragment onSaveInstanceState(当视图已经被销毁时)。

这里的问题是,在将代码转换为 kotlin 并使用合成进行视图访问后,当我想保存 recyclerview 第一个可见元素以在之后恢复时,我在 onSaveInstanceState 中得到 NullPointerException

val firstVisiblePosition = (recycler_view_cities.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()

使用旧的 java 实现,它可以正常工作,因为我将 recycler_view_cities 的引用存储在 Fragment 中,我可以在那里访问它。

  • 问题 1. CitiesFragment 的 onSaveInstance 状态不应该在 onStop 和 onDestroyView 之前调用吗?
  • 问题2,这种情况如何处理?

【问题讨论】:

    标签: android android-fragments kotlin-android-extensions onsaveinstancestate


    【解决方案1】:

    不应该在 onStop 和 onDestroyView 之前调用 CitiesFragment 的 onSaveInstanceState 吗?

    不一定。来自onSaveInstanceState() 的片段文档:

    这对应于 {@link Activity#onSaveInstanceState(Bundle) Activity.onSaveInstanceState(Bundle)} 和那里的大部分讨论 这里也适用。但请注意:此方法可能会被调用 在 onDestroy() 之前的任何时间。有很多情况 碎片可能大部分被拆除的地方(例如当放置在 没有显示 UI 的返回堆栈),但它的状态将不会被保存,直到 它拥有的活动实际上需要保存它的状态。

    onSaveInstanceState() 将在活动关闭时被活动调用(除非用户明确关闭活动)。您的 Fragment 收到回调,但可以处于 onDestroy 之前的任何状态,这意味着 UI 可能已经被拆除。

    遇到这种情况怎么办?

    检查 UI 是否存在于onSaveInstanceState()

    if (fragment.getView() != null) {
       // Your stuff
    }
    

    【讨论】:

    • 我需要 onSaveInstanceState 来保存视图状态(recycler_view_cities 中的第一个可见项),但如果 view == null,这将毫无意义。 recycler_view_cities 本身是通过 kotlin 合成使用的,并且引用随视图一起消失了
    • @OlegZolotar 您无法从不存在的视图中保存 UI 状态。当WeatherFragment 被添加到后台堆栈时,onDestroyView() 会在 CitiesFragment 上调用。您是否使用replaceadd 进行片段交易? replace 会导致 onDestroyView() 被调用,也许这不是你想要的?
    • 我正在使用replace 进行片段交易,因为我想删除CitiesFragment 并为所选城市显示WeatherFragment。而且我还想知道CitiesFragment 中的第一个可见项目,以便能够在用户返回时恢复滚动位置。有什么建议如何实现这两种说法?
    • @Oliver1123 如果你想显示城市的天气片段,然后返回城市片段,我会在片段交易中使用add而不是replace,并且在片段交易中也使用addToBackStack()片段交易。我什至不确定您的用例是否需要onSaveInstanceState。我尝试使用addreplace 制作片段,我尝试重新创建活动...。recyclerview 保持正确的滚动索引:/
    猜你喜欢
    • 2022-12-15
    • 2013-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 2021-09-08
    • 1970-01-01
    相关资源
    最近更新 更多