一、Fragment的第五大組件
1.Fragment的加載方式
- 靜態加載
直接在xml布局中添加Fragment
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"/>
- 動態加載
Fragment的動態加載是由Fragment事務驅動,Fragment事務就是:對Fragment進行添加、移除、替換或執行其它動作,提交給Activity的每一個變化;
添加:add() 、移除:remove()、替換:replace()、提交事務: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)設置viewpager左右預加載頁
- FragmentPagerAdapter:將每一個生成的Fragment保存在內存中,limit外Fragment沒有銷毀,生命周期為onPause>onStop>onDestroyView,onCreateView->onStart->onResume,但Fragment的成員變量都沒有變,所以可以緩存根View,避免重復inflate
- FragmentStatePagerAdapter:對limit外的Fragment銷毀,生命周期為onPause->onStop->onDestoryView->onDestory->onDetach, onAttach->onCreate->onCreateView->onStart->onResume。
使用場景:對于需要緩存在內存中的固定較少數量的靜態頁面使用FragmentPagerAdapter,如引導頁,Tab頁面;對于擁有大量頁面的情況應使用FragmentStatePagerAdapter避免占用大量內存,如圖片預覽
二、Fragment的生命周期
三、Fragment的通訊方式
- Fragment獲取它所在的Activity,通過getActivity()強制轉換調用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中添傳遞數據
setArguments(Bundle bundle) - Fragment中定義內部回調接口,Activity中注冊
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.通過fragment中的事務 add(),replace(),remove()等操作
2.通過Fragment的hide(),show()來顯示
3.通過Fragment的detach()&attach()來分離Activity
區別:第一種方式是直接銷毀實例,創建和添加都有些影響性能,第二種是不銷毀實例和視圖,仍然占用內存,第三種是不銷毀實例,但銷視圖,重新加載onCreateView。
五、Fragment的懶加載
1.ViewPager為什么要懶加載,什么情況適用
ViewPager的setOffScreenPageLimit()方法默認limit為1,既會預加載左右頁面,而為了節省流量,理想情況是當用戶切換到該界面時才會調用網絡請求獲取數據。相關方法為setUserVisibleHint(),當前頁面為true,預加載頁面為false,只有Fragment從可見到不可見或者從不可見到可見時會調用,Fragment初次創建時setUserVisibleHint先于onCreateView()調用,所以可以由此判斷Fragment是否初始創建。
ViewPager首次顯示的頁面經過方法調用
->setUserVisibleHint(false)
->setUserVisibleHint(true)
->onCreateView()...,所以該頁面的數據加載放在onCreateView中;其它預加載頁面預加載時setUserVisibleHint(false)
->onCreateView()...,當選中該頁面顯示時調用setUserVisibleHint(true),所以預加載頁面數據加載放在setUserVisibleHint中。
2.注意事項
果想通過adapter.notifyDataSetChanged來刷新頁面時,必須繼承FragmentStatePagerAdapter,因為FragmentPagerAdapter會緩存Fragment,不會走getItem方法,同時將所要刷新頁面的getItemPosition返回POSITION_NONE