[英]Navigation Architecture Component - OnBackPressed() - Android
我使用 Android 导航架构在片段中取得进展。
当我在最后一个屏幕上按下键或在屏幕上放置一个按钮并将按钮 function 设置为
val navıgattor = activity.findNavController(R.id.nav_host_fragment)
navigator.popBackStack()
并点击,我回到了上一个fragment,但是又调用了上一个fragment中的onCreateView()方法。 我期待它保持 state 的正常行为。
我在哪里做错了?
我分两部分回答——
解决方案:
每次返回上一个片段时不要放大视图。 将 View 保存在局部变量中并仅对其进行一次膨胀。 由Ian Lake推荐这里
private var savedViewInstance: View? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return if (savedViewInstance != null) {
savedViewInstance
} else {
savedViewInstance =
inflater.inflate(R.layout.fragment_professional_details, container, false)
savedViewInstance
}
}
解释
您得到的行为是默认行为,片段将在您每次调用navigator.popBackStack()
或使用设备上的后退按钮时重新创建它们的视图。
让我们了解导航架构下片段的生命周期。
场景:我们采用两个片段,HomeFragment 和 DashboardFragment。 两个片段都属于同一个 NavGraph,起始目的地是 Home Fragment。
应用程序启动时的片段生命周期-
HomeFragment:onAttach:
HomeFragment: onCreate:
HomeFragment:onCreateView:
HomeFragment:onViewCreated:
HomeFragment:onActivityCreated:
HomeFragment:onStart:
HomeFragment: onResume:
在导航上:主页片段 ---> 仪表板片段
仪表板片段:onAttach:
仪表板片段:onCreate:
仪表板片段:onCreateView:
仪表板片段:onViewCreated:
DashboardFragment:onActivityCreated:
仪表板片段:onStart:
仪表板片段: onResume:
HomeFragment:onPause:
HomeFragment:onStop:
HomeFragment: onDestroyView:
在导航上:仪表板片段 ---> 主页片段
HomeFragment:onAttach:
HomeFragment: onCreate:
HomeFragment:onCreateView:
HomeFragment:onViewCreated:
HomeFragment:onActivityCreated:
HomeFragment:onStart:
HomeFragment: onResume:
仪表板片段:onPause:
DashboardFragment: onStop:
HomeFragment: onDestroy:
仪表板片段:onDestroyView:
仪表板片段:onDestroy:
如果我们在初始 HomeFragment: onCreateView() 上保存视图并在每次调用 HomeFragment: onCreateView() 时膨胀相同的视图,我们可以恢复旧视图。
如果您注意到HomeFragment: onDestroy()
将被调用,但在HomeFragment: onViewCreated()
调用之后。 HomeFragment: onDestroy()
只是破坏 HomeFragment 的旧实例。
我仍然相信这种做事方式不是最佳实践,但直到谷歌会提出类似onFragemntRestore()
的东西。
另一方面,假设每次删除或替换片段时都会重新创建片段,并且您应该使用onSaveInstanceState()
恢复那里的状态。
ViewModel 来了保存片段 state 并恢复它们的喧嚣。 要实际更新视图,您必须需要 ViewModel 并观察视图中的更改。
简而言之,如果您有
something
可以为您的视图处理数据,无论您身在何处,如果您返回相同的 position 而不进行任何更改,则该something
包含有关您之前查看的信息。 那something
ViewModel
。
还有很多其他值得一读的关于同一个主题的文章,比如这个, 这个和这个
快乐编码!
从片段文档:
/**
* Called when the view previously created by {@link #onCreateView} has
* been detached from the fragment. The next time the fragment needs
* to be displayed, a new view will be created. This is called
* after {@link #onStop()} and before {@link #onDestroy()}. It is called
* <em>regardless</em> of whether {@link #onCreateView} returned a
* non-null view. Internally it is called after the view's state has
* been saved but before it has been removed from its parent.
*/
public void onDestroyView()
因此,无论何时调用 onDestroyView (无论出于何种原因),当片段回到顶部时,您都会看到 onCreateView 被调用。 为了重新获得视图的 state,需要考虑一些工具(您可以决定哪一种或哪种组合适合您):
1-覆盖onSaveInstanceState,将当前state作为bundle传递,并在android系统以bundle作为参数调用onCreateView时重用它。
2- 使用包含视图 state 信息的ViewModel ,该信息与 Fragment、其视图或其父 Activity 绑定,并与此类信息一起被销毁。
3- 在片段中保留由 onCreateView 返回的视图 object 的副本,并在再次调用 onCreateView 时重新使用它,如果不是 null (请谨慎使用,因为某些视图可能会在重绘时遇到麻烦,例如OSM MapView ):
private var viewCopy : View? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
if(viewCopy!=null)
return viewCopy
...
viewCopy = inflatedView
return viewCopy
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.