导航组件生命周期

Navigation Component Lifecycle

我已经试用了一段时间的导航组件,但不知何故没有得到当前导航组件生命周期背后的原因(或解释)。这里有一些需要澄清的地方。

1。片段到片段流

在导航组件中,每次访问(或重新访问)时都会重新创建每个片段(或者说页面)。因此,当您在 A 并转到 B 时,A 会被销毁,稍后当您返回 A 时(例如按后退按钮)A由拉伸创建。

在传统的 Activity 模式中,当您返回 A 时,它只会转到 onResume,因为它在移动到 B 时没有被破坏。导航组件中更改此模式的任何原因?

重新创建的问题是当你有很多数据并且重新绘制需要时间并且感觉应用程序冻结时。一个例子是简单的主页(比如 Facebook NewsFeed)。可以使用 ViewModel 处理保存数据,但再次绘制所有提要需要时间,并且会冻结。

还有一个游戏产生的问题。假设这种情况:A 有一个 Collapsing AppBar 和一个 NestedScrollView。用户向下滚动,AppBar 将折叠,然后用户移动到另一个页面 B。当他回到 A 时,它会被重新绘制并且 AppBar 被扩展。我不确定这是一个错误还是我应该做些什么来修复它?所以这里也欢迎任何解决方案。

2。 Activity休闲

如果 activity 由于某些原因(例如方向更改)而重新创建,则导航组件中的每个页面都会重新创建,直到当前目的地。尽管 onCreate 片段的方法不是 onCreateView 被调用,但我没有看到在 Activity 娱乐中创建片段的意义。欢迎任何解释。

导航组件目前仅支持片段替换。因此,您将无法像使用手动片段事务那样添加 () 片段。

但是,如果您担心片段的 re-inflating 布局和 re-fetching 数据,可以使用以下两种方法轻松解决。

创建视图后,将其存储在一个变量中,并在调用 onCreateView() 时使用它。

private var view: View? = null

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

    if (view == null) {
        view = inflater.inflate(R.layout.fragment_list, container, false)
                //...
    }

    return view

 }

来源:https://twitter.com/ianhlake/status/1103522856535638016

将 ViewModel 与 Fragment 一起使用,并将所需的数据保存为成员变量。这样,替换关联片段时,数据不会被清除。 ViewModel 仅在片段的 onDestroy() 上被清除,这只会在您销毁父级 activity 时发生。 https://developer.android.com/images/topic/libraries/architecture/viewmodel-lifecycle.png

迁移到 Navigation library 时,我们使用片段桥接数据和视图的方式略有变化,而且变化良好。它迫使我们区分 FragmentView 生命周期。

Pre-navigation:使用 FragmentlifecycleScope.

onCreate() 中观察 LiveData
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
...
import kotlinx.android.synthetic.main.old_fragment.*

class OldFragment : Fragment(R.layout.old_fragment) {
  private val vm by activityViewModels<MainViewModel>()

  override fun onCreate(savedInstanceState: Bundle?) {
    vm.getLiveData().observe(this) { data ->
      oldTextView.text = data.name
    }
  }
}

导航:使用 viewLifecycleOwner 范围在 onViewCreated() 中观察 LiveData

...

class NewFragment : Fragment() {
  private val vm by activityViewModels<MainViewModel>()

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    vm.getLiveData().observe(viewLifecycleOwner) { data ->
      oldTextView.text = data.name
    }
  }
}

重点说明:

  1. 并非所有生命周期所有者都是相同的。重新创建视图时片段生命周期不会执行观察者(使用导航库和导航时 up/back)。
  2. 在创建视图之前无法访问 viewLifecycleOwner

希望这有助于防止在开发人员迁移到 Navigation 时替换 LiveData 代码。