我已经尝试了一段时间的导航组件,但是以某种方式没有得到当前导航组件生命周期背后的原因(或解释)。这里有一些需要澄清的地方。
在导航组件中,每次访问(或重新访问)时都会重新创建每个片段(或说页面)。因此,当您在A
处并转到B
时,A
被销毁,随后当您返回到A
时(如按返回按钮)A
从拉伸创建。
在传统的活动模式中,当您返回到A
时,它只会转到onResume
,因为它移到B
时并没有被破坏。导航组件中是否更改了此模式的任何原因?
重新创建的问题是,当您有大量数据并且需要重绘时间时,感觉就像应用程序冻结了一样。一个简单的主页就是一个例子(例如Facebook NewsFeed)。可以使用ViewModel
处理保留数据,但是再次绘制所有提要需要时间,并且将冻结。
娱乐产生了另一个问题。假定这种情况:A
的{{1}}和Collapsing AppBar
。用户向下滚动,NestedScrollView
将折叠,然后用户移至另一个页面AppBar
。当他回到B
时,它将重新绘制,并展开A
。我不确定这是一个错误还是应该做些修复?因此,这里也欢迎任何解决方案。
如果由于某些原因(例如方向改变)而重新创建活动,则会重新创建导航组件中的每个页面,直到当前目标为止。尽管调用了不是AppBar
的Fragment的onCreate
方法,但我看不出在Activity娱乐中创建Fragments的意义。任何解释都将受到欢迎。
答案 0 :(得分:2)
导航组件目前仅支持片段替换。因此,您将无法像手动片段事务那样添加()片段。
但是,如果您担心要重新扩大布局并重新获取片段的数据,则可以通过以下两种方法轻松解决。
创建视图后,将其存储在变量中,并在调用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一起使用,并将所需的数据作为成员变量保存。这样,替换关联的片段时不会清除数据。仅在片段的onDestroy()上清除ViewModel,这仅在销毁父活动时才会发生。 https://developer.android.com/images/topic/libraries/architecture/viewmodel-lifecycle.png
答案 1 :(得分:1)
在迁移到Navigation library时,我们使用片段桥接数据和视图的方式发生了微小的变化,并且变化很好。它迫使我们区分Fragment
和View
生命周期。
预导航:使用LiveData
的{{1}}观察onCreate()
中的Fragment
。
lifecycleScope
导航:使用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
}
}
}
范围观察LiveData
中的onViewCreated()
。
viewLifecycleOwner
主要注意事项:
...
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
}
}
}
。希望这可以防止开发人员迁移到导航时替换viewLifecycleOwner
代码。