1.getActivity() 引用問題
使用中听盖,經常會在 Fragment 中通過 getActivity()
獲取到宿主 Activity 對象亥鬓,但稍有不慎便會引發(fā)下面這兩個問題:
第一個运提, Activity 的實例銷毀問題。比如霞玄,Fragment 中存在類似網絡請求之類的異步耗時任務窜司,當該任務執(zhí)行完畢回調 Fragment 的方法并用到宿主 Activity 對象時,很有可能宿主 Activity 對象已經銷毀蹲坷,從而引發(fā) NullPointException
等異常驶乾,甚至造成程序崩潰。
所以循签,異步回調時需要注意添加空值等判斷(譬如:fragment.isAdd()
级乐,getActivity()!=null
等),或者在 Fragment 創(chuàng)建實例時就通過 getActivity().getApplicationContext()
方法保存整個應用的上下文對象县匠,再來使用风科;
第二個,內存泄漏問題乞旦。如果 Fragment 持有宿主 Activity 的引用丐重,會導致宿主 Activity 無法回收,造成內存泄漏杆查。所以扮惦,如果可以的話,盡量不要在 Fragment 中持有宿主 Activity 的引用亲桦。
為了解決 Context 上下文引用的問題崖蜜,Fragment 提供了一個 onAttach(context)
方法,在此方法中我們可以獲取到 Context 對象客峭,如下
@Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
2.onActivityResult(int requestCode, int resultCode, Intent intent)
requestCode:請求碼(指出該方法是從哪個請求的結果觸發(fā)的)
resultCode:Activity返回的結果碼(指出返回的數據來自于哪個新的Activity)
Fragment 類提供有 startActivityForResult()
方法用于 Activity 間的頁面跳轉和數據回傳豫领,其實內部也是調用 Activity 的對應方法。但是在頁面返回時需要注意 Fragment 沒有提供 setResult()
方法(設置返回處理結果)舔琅,可以通過宿主 Activity 實現等恐。
舉個例子,在 ActivityA 中的 FragmentA 里面調用 startActivityForResult()
跳轉至 ActivityB 中备蚓,并在 ActivityB 中的 FragmentB 里面返回到 ActivityA
// FragmentA 中頁面跳轉和數據回傳
...
Intent intent = new Intent(getContext(), ActivityB.class);
getActivity().startActivityForResult(intent, 0);
// FragmentB 里面返回到 ActivityA
Intent intent = new Intent(getActivity(), ActivityA.class);
intent.putExtra("test", test);
getActivity().setResult(0, intent);
getActivity().finish();
在回調時课蔬,先會回調 ActivityA 中的 onActivityResult() 方法,然后再分發(fā)回調 FragmentA 中的 onActivityResult() 方法郊尝。
// 回調 ActivityA 中的 onActivityResult() 方法
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
// 處理特定的結果
if (requestCode == 0 && resultCode == 0) {
// 取出Intent里的Extras數據
Bundle data = intent.getExtras();
// 取出Bundle中的數據
String result = data.getString("test");
Toast.makeText(getApplicationContext(), result, 0).show();
}
}
}
...
// 回調 FragmentA 中的 onActivityResult() 方法
...
3.getChildFragmentManager()
Activity:getFragmentManager()
在 Activity 嵌入 Fragment 時二跋,需要使用 FragmentManager,通過 Activity 提供的 getSupportFragmentManager()
方法即可獲取流昏,用于管理 Activity 里面嵌入的所有一級 Fragment扎即。
Fragment:getChildFragmentManager()
但是對于繼續(xù)嵌套二級甚至三級 Fragment吞获,即 Activity 嵌套多級 Fragment。此時在 Fragment 里管理子 Fragment 時谚鄙,也需要使用到 FragmentManager各拷。但是一定要使用 getChildFragmentManager()
方法獲取 FragmentManager 對象。
4.Fragment + ViewPager
ViewPager 提供了兩種頁面適配器來管理不同 Fragment 之間的滑動切換:FragmentPagerAdapter
和 FragmentStatePagerAdapter
闷营。
使用 FragmentPagerAdapter 時烤黍,ViewPager 中的所有 Fragment 實例常駐內存,當 Fragment 變得不可見時僅僅是視圖結構的銷毀粮坞,即調用了 onDestroyView() 方法蚊荣。由于 FragmentPagerAdapter 內存消耗較大,所以適合少量靜態(tài)頁面的場景莫杈。
使用 FragmentStatePagerAdapter 時互例,當 Fragment 變得不可見,不僅視圖層次銷毀筝闹,實例也被銷毀媳叨,即調用了 onDestroyView() 和 onDestroy() 方法,僅僅保存 Fragment 狀態(tài)关顷。相比而言糊秆, FragmentStatePagerAdapter 內存占用較小,所以適合大量動態(tài)頁面议双,比如我們常見的新聞列表類應用痘番。