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
的FragmentManager
getChildFragmentManager
与fragment
关联,可以将其视为fragment
的FragmentManager
getParentFragmentManager
情况稍微复杂,正常情况返回的是该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`仅存储片段的`