這個(gè)問題一直搜索相關(guān)資料沒發(fā)現(xiàn),后來還是自己瞎琢磨解決的析孽,主要問題還是沒仔細(xì)研究源碼弄清原理岳瞭。
在開始詳細(xì)講解之前火的,先幾句話概括下問題和解決方式
- 在模擬自動(dòng)銷毀界面并恢復(fù)數(shù)據(jù)時(shí),F(xiàn)ragmentStateAdapter發(fā)現(xiàn)一直創(chuàng)建Fragment內(nèi)嵌的Fragment伶唯。
解決方式:以標(biāo)簽形式創(chuàng)建內(nèi)嵌Fragment,在發(fā)現(xiàn)如果已經(jīng)存在標(biāo)簽的內(nèi)嵌Fragment的時(shí)候,便不再創(chuàng)建加入遭铺。
什么是內(nèi)嵌Fragment?
FragmentStateAdapter 本身以多個(gè)Fragment以Tab形式顯示恢准,然后這些Fragment里面再內(nèi)嵌Fragment,就是內(nèi)嵌Fragment了
為什么導(dǎo)致這個(gè)一直創(chuàng)建Fragment的問題魂挂?
因?yàn)镕ragmentStateAdapter已經(jīng)處理了保存View狀態(tài)、恢復(fù)View狀態(tài)馁筐,也包括恢復(fù)ChildFragment涂召。我們?cè)诨謴?fù)的時(shí)候,如果不做特殊處理敏沉,會(huì)再次運(yùn)行onViewCreated代碼再次創(chuàng)建ChildFragment
如何解決果正?
我們只要在創(chuàng)建ChildFragment的時(shí)候加入標(biāo)簽Fragment的判斷即可避免重復(fù)創(chuàng)建
// 先通過標(biāo)簽形式查找
val matissFragment = childFragmentManager.findFragmentByTag(MATISS_FRAGMENT_TAG)
// 如果不存在,則重新創(chuàng)建并添加盟迟,如果已經(jīng)存在就不用處理了秋泳,因?yàn)镕ragmentStateAdapter已經(jīng)幫我們處理了
matissFragment ?: let {
val newMatissFragment = MatissFragment.newInstance(
arguments?.getInt(MatissFragment.ARGUMENTS_MARGIN_BOTTOM)
?: 0
)
childFragmentManager.beginTransaction()
.add(R.id.fragmentContainerView, newMatissFragment, MATISS_FRAGMENT_TAG)
.commitAllowingStateLoss()
}
題外話
有關(guān)數(shù)據(jù)的恢復(fù)等等,該用ViewModel或者用其他方式時(shí)候的實(shí)現(xiàn)還是要用的攒菠,這個(gè)更多的是恢復(fù)View方面
代碼例子
可以學(xué)習(xí)下面的源碼迫皱,內(nèi)嵌Fragment的形式顯示
一個(gè)非常豐富的開源庫,如果你需要相冊(cè)辖众、錄制卓起、錄音等操作,那么這個(gè)也許對(duì)你有一定的幫助: