一、Fragment的第五大組件
1.Fragment的加載方式
- 靜態(tài)加載
直接在xml布局中添加Fragment
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"/>
- 動(dòng)態(tài)加載
Fragment的動(dòng)態(tài)加載是由Fragment事務(wù)驅(qū)動(dòng),F(xiàn)ragment事務(wù)就是:對(duì)Fragment進(jìn)行添加、移除、替換或執(zhí)行其它動(dòng)作,提交給Activity的每一個(gè)變化;
添加:add() 、移除:remove()、替換:replace()、提交事務(wù):commit()等方法
FragmentManager fragmentManager=getSupportFragmentManager();
fragmentManager.beginTransaction().add(new Fragment(), "TAG").commit();
fragmentManager.beginTransaction().remove(new Fragment()).commit();
// Fragment中嵌套Fragment
getChildFragmentManager().beginTransaction().remove(rescueChatFragment).commitAllowingStateLoss();
2.FragmentPagerAdapter與FragmentStatePagerAdapter
- setOffScreenPageLimit(int limit)設(shè)置viewpager左右預(yù)加載頁(yè)
- FragmentPagerAdapter:將每一個(gè)生成的Fragment保存在內(nèi)存中,limit外Fragment沒(méi)有銷毀,生命周期為onPause>onStop>onDestroyView,onCreateView->onStart->onResume,但Fragment的成員變量都沒(méi)有變,所以可以緩存根View,避免重復(fù)inflate
- FragmentStatePagerAdapter:對(duì)limit外的Fragment銷毀,生命周期為onPause->onStop->onDestoryView->onDestory->onDetach, onAttach->onCreate->onCreateView->onStart->onResume。
使用場(chǎng)景:對(duì)于需要緩存在內(nèi)存中的固定較少數(shù)量的靜態(tài)頁(yè)面使用FragmentPagerAdapter,如引導(dǎo)頁(yè),Tab頁(yè)面;對(duì)于擁有大量頁(yè)面的情況應(yīng)使用FragmentStatePagerAdapter避免占用大量?jī)?nèi)存,如圖片預(yù)覽
二、Fragment的生命周期

三、Fragment的通訊方式
- Fragment獲取它所在的Activity,通過(guò)getActivity()強(qiáng)制轉(zhuǎn)換調(diào)用Activity中的方法。
((HomeActivity) context).onStartProgress();
((HomeActivity) context).onStopProgressError();
- Activity獲取它所包含的Fragment信息
// Activity中
getSupportFragmentManager().beginTransaction().add(R.id.flSpotChat, spotChatFragment).commit()
// Fragment嵌套
getChildFragmentManager().beginTransaction().add(R.id.flRescueChat, rescueChatFragment).commitAllowingStateLoss();
- Activity想Fragment中添傳遞數(shù)據(jù)
setArguments(Bundle bundle) - Fragment中定義內(nèi)部回調(diào)接口,Activity中注冊(cè)
public interface OnSosWhoCheckListener {
/**
* 3:為自己呼救 1.為其他人呼救
*
* @param sosWho
*/
void onCheck(String sosWho);
}
private OnSosWhoCheckListener onSosWhoCheckListener;
public SpotSosDialogFragment setOnSosWhoCheckListener(OnSosWhoCheckListener onSosWhoCheckListener) {
this.onSosWhoCheckListener = onSosWhoCheckListener;
return this;
}
spotSosDialogFragment = new SpotSosDialogFragment()
.setBundle(bundle)
.setOnSosWhoCheckListener(sosWho -> {
SpotFragment.this.sosWho = sosWho;
SpotFragment.this.sosType = "1";
}).setOnContractListener(contractors -> {
SpotFragment.this.contractors = contractors;
SpotFragment.this.sosType = "2";
});
四、Fragment的切換方式
1.通過(guò)fragment中的事務(wù) add(),replace(),remove()等操作
2.通過(guò)Fragment的hide(),show()來(lái)顯示
3.通過(guò)Fragment的detach()&attach()來(lái)分離Activity
區(qū)別:第一種方式是直接銷毀實(shí)例,創(chuàng)建和添加都有些影響性能,第二種是不銷毀實(shí)例和視圖,仍然占用內(nèi)存,第三種是不銷毀實(shí)例,但銷視圖,重新加載onCreateView。
五、Fragment的懶加載
1.ViewPager為什么要懶加載,什么情況適用
ViewPager的setOffScreenPageLimit()方法默認(rèn)limit為1,既會(huì)預(yù)加載左右頁(yè)面,而為了節(jié)省流量,理想情況是當(dāng)用戶切換到該界面時(shí)才會(huì)調(diào)用網(wǎng)絡(luò)請(qǐng)求獲取數(shù)據(jù)。相關(guān)方法為setUserVisibleHint(),當(dāng)前頁(yè)面為true,預(yù)加載頁(yè)面為false,只有Fragment從可見(jiàn)到不可見(jiàn)或者從不可見(jiàn)到可見(jiàn)時(shí)會(huì)調(diào)用,F(xiàn)ragment初次創(chuàng)建時(shí)setUserVisibleHint先于onCreateView()調(diào)用,所以可以由此判斷Fragment是否初始創(chuàng)建。
ViewPager首次顯示的頁(yè)面經(jīng)過(guò)方法調(diào)用
->setUserVisibleHint(false)
->setUserVisibleHint(true)
->onCreateView()...,所以該頁(yè)面的數(shù)據(jù)加載放在onCreateView中;其它預(yù)加載頁(yè)面預(yù)加載時(shí)setUserVisibleHint(false)
->onCreateView()...,當(dāng)選中該頁(yè)面顯示時(shí)調(diào)用setUserVisibleHint(true),所以預(yù)加載頁(yè)面數(shù)據(jù)加載放在setUserVisibleHint中。
2.注意事項(xiàng)
果想通過(guò)adapter.notifyDataSetChanged來(lái)刷新頁(yè)面時(shí),必須繼承FragmentStatePagerAdapter,因?yàn)镕ragmentPagerAdapter會(huì)緩存Fragment,不會(huì)走getItem方法,同時(shí)將所要刷新頁(yè)面的getItemPosition返回POSITION_NONE