在
Android Jetpack组件中,fragment作为视图控制器之一占有很重要的位置。但由于其bug众多,暗坑无数,以至于 Square 有这样一篇博客:Advocating Against Android Fragments。github上的 Fragmentation 有着 9.4k 的star。而现在,
androidx fragment稳定版已来到 1.2.2,让我们总结一下fragment有哪些常见问题以及有哪些使用fragment的新姿势
Fragment 常见的问题
-
getSupportFragmentManager , getParentFragmentManager 和 getChildFragmentManager
-
FragmentStateAdapter 和 FragmentPagerAdapter
-
add 和 replace
-
observe LiveData时传入 this 还是 viewLifecycleOwner
-
使用 simpleName 作为 fragment 的 tag 有何风险?
-
在 BottomBarNavigation 和 drawer 中如何使用Fragment多次添加?
-
返回栈
getSupportFragmentManager , getParentFragmentManager和getChildFragmentManager
FragmentManager是androidx.fragment.app(已弃用的不考虑)下的抽象类,创建用于 添加,移除,替换fragment的事务(transaction)
首先要确认一件事,getSupportFragmentManager()是 FragmentActivity下的方法
getParentFragmentManager 和 getChildFragmentManager 是 androidx.fragment.app.Fragment 下的方法,
其中
androidx.fragment 1.2.0后getFragmentManager与requireFragmentManager已弃用
明确了这件事,接下来的就很清晰了
getSupportFragmentManager与activity关联,可以将其视为activity的FragmentManagergetChildFragmentManager与fragment关联,可以将其视为fragment的FragmentManagergetParentFragmentManager情况稍微复杂,正常情况返回的是该fragment依附的activity的FragmentManager。如果该fragment是另一个fragment的子fragment,则返回的是其父fragment的getChildFragmentManager
如果这么说还不明白的话,我们可以做一个实践。
创建一个 activity,一个父fragment ,一个子fragment
// activity
class MyActivity : AppCompatActivity(R.layout.activity_main) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportFragmentManager.commit {
add<ParentFragment>(R.id.content)
}
Log.i("MyActivity", "supportFragmentManager $supportFragmentManager")
}
}
class ParentFragment : Fragment(R.layout.fragment_parent) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
childFragmentManager.commit {
add<ChildFragment>(R.id.content)
}
Log.i("ParentFragment", "parentFragmentManager $parentFragmentManager")
Log.i("ParentFragment", "childFragmentManager $childFragmentManager")
}
}
class ChildFragment : Fragment(R.layout.fragment_child) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Log.i("ChildFragment", "parentFragmentManager $parentFragmentManager")
Log.i("ChildFragment", "childFragmentManager $childFragmentManager")
}
}
//log
I/MyActivity: supportFragmentManager FragmentManager{825dcef in HostCallbacks{14a13fc}}}
I/ParentFragment: parentFragmentManager FragmentManager{825dcef in HostCallbacks{14a13fc}}}
I/ParentFragment: childFragmentManager FragmentManager{df5de83 in ParentFragment{7cdd800}}}
I/ChildFragment: parentFragmentManager FragmentManager{df5de83 in ParentFragment{7cdd800}}}
I/ChildFragment: childFragmentManager FragmentManager{aba9afb in ChildFragment{5cea718}}}
因此
-
在
activity中使用ViewPager,BottomSheetFragment和DialogFragment时,都应使用getSupportFragmentManager -
在
fragment中使用ViewPager时应该使用getChildFragmentManager
错误的在 fragment 中使用 activity 的 FragmentManager 会引发内存泄露。 为什么呢?假如您的fragment中有一些依靠 ViewPager 管理的子 fragment,并且所有这些 fragment 都在 activity 中,因为您使用的是activity 的FragmentManager 。 现在,如果关闭您的父fragment,它将被关闭,但不会被销毁,因为所有子fragment都处于活动状态,并且它们仍在内存中,从而导致泄漏。 它不仅会泄漏父fragment,还会泄漏所有子fragment,因为它们都无法从堆内存中清除。
FragmentStateAdapter 和 FragmentPagerAdapter
FragmentPagerAdapter将整个 fragment存储在内存中,如果ViewPager中使用了大量 fragment,则可能导致内存开销增加。 FragmentStatePagerAdapter仅存储片段的savedInstanceState,并在失去焦点时销毁所有 fragment。
让我们看看常见的两个问题
1. 刷新ViewPager不生效
ViewPager 中的 fragment 是通过 activity或 fragment的 FragmentManager 管理的,FragmentManager 包含了viewpager的所有fragment的实例
因此,当ViewPager没有刷新时,它只是FragmentManager仍保留的旧 fragment 实例。 您需要找出为什么FragmentManger持有fragment实例的原因。
2. 在Viewpager中访问当前fragment
这也是我们遇到的一个非常普遍的问题。 如果遇到这种情况,我们一般在 adapter 内部创建 fragment 的数组列表,或者尝试使用某些标签访问fragment。 不过还有另一种选择。 FragmentStateAdapter 和FragmentPagerAdapter都提供方法setPrimaryItem。 可以用来设置当前fragment,如下所示:
var fragment: ChildFragment? = null
override fun setPrimaryItem(container: ViewGroup, position

本文详细探讨了Android Jetpack中的Fragment常见问题,如getSupportFragmentManager的使用,FragmentStateAdapter与FragmentPagerAdapter的区别,add与replace的选择,以及LiveData的观察策略。此外,还介绍了Fragment的新特性,如fragment-ktx的扩展函数,FragmentFactory的使用,Fragment返回键拦截,以及Fragment与Activity的通信等,帮助开发者更好地理解和运用Fragment。
最低0.47元/天 解锁文章
1485

被折叠的 条评论
为什么被折叠?



