【问题标题】:Navigation Component Lifecycle导航组件生命周期
【发布时间】:2019-06-25 07:41:22
【问题描述】:

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

1。片段到片段流

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

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

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

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

2。活动休闲

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

【问题讨论】:

  • 您的nav_graph 可能有问题。总是有fragment backstack。即使在导航组件中
  • 我实际上并没有在我的nav_graph上添加任何额外内容
  • 后栈有效,但我的意思是它转到后堆叠片段的onCreateView 并被重绘

标签: android android-fragments android-jetpack android-architecture-navigation


【解决方案1】:

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

但是,如果您担心重新膨胀布局和重新获取片段的数据,则可以通过以下两种方法轻松解决。

创建视图后,将其存储在一个变量中,并在调用 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 一起使用,并将所需的数据保存为成员变量。这样,替换关联的fragment时,数据不会被清除。 ViewModel 仅在片段的 onDestroy() 上被清除,这只会在您销毁父活动时发生。 https://developer.android.com/images/topic/libraries/architecture/viewmodel-lifecycle.png

【讨论】:

  • 但是,这将在替换后每隔 onBackPressed 重置view 变量。还有其他解决方案吗?
【解决方案2】:

当迁移到Navigation library 时,我们使用片段来连接数据和视图的方式发生了轻微的变化,而且方式很好。它迫使我们区分Fragment 和View 生命周期。

预导航:使用Fragment 的lifecycleScope 观察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. 并非所有生命周期所有者都是相同的。重新创建视图时(在使用导航库和向上/向后导航时),片段生命周期不会执行观察者。
  2. 在创建视图之前无法访问viewLifecycleOwner。

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

【讨论】:

    猜你喜欢
    • 2017-10-17
    • 1970-01-01
    • 2018-10-13
    • 2018-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-26
    相关资源
    最近更新 更多