1. 程式人生 > >全面升級Android面試之fragment面試題集

全面升級Android面試之fragment面試題集

1.Fragment為什麼被稱為第五大元件

答:Fragment比Activity更節省記憶體,其切換模式也更加舒適,使用頻率不低於四大元件,且有自己的生命週期,並且必須依付於Activity

2.Activity建立Fragment的方式

靜態建立具體步驟
首先我們同樣需要註冊一個xml檔案,然後建立與之對應的java檔案,通過onCreatView()的返回方法進行關聯,最後我們需要在Activity中進行配置相關引數即在Activity的xml檔案中放上fragment的位置。

動態建立具體步驟
(1)建立待新增的碎片例項
(2)獲取FragmentManager,在活動中可以直接通過呼叫 getSupportFragmentManager()方法得到。
(3)開啟一個事務,通過呼叫beginTransaction()方法開啟。
(4)向容器內新增或替換碎片,一般使用repalce()方法實現,需要傳入容器的id和待新增的碎片例項。
(5)提交事務,呼叫commit()方法來完成。

3.FragmentPageAdapter和FragmentPageStateAdapter的區別

答:FragmnetPageAdapter在每次切換頁面時,只是將Fragment進行分離,適合頁面較少的Fragment使用以儲存一些記憶體,對系統記憶體不會多大影響
FragmentPageStateAdapter在每次切換頁面的時候,是將Fragment進行回收,適合頁面較多的Fragment使用,這樣就不會消耗更多的記憶體

4Fragment的生命週期

這裡寫圖片描述
首先既然Fragment必須依附於Activity才能存在,我們就來具體分析一下

執行狀態
當一個碎片是可見的,並且它所關聯的活動正處於執行狀態時,該碎片也處於執行狀態

暫停狀態
當一個活動進入暫停狀態時(由於另一個未佔滿螢幕的活動被新增到棧頂),與它相關聯的可見碎片就會進入到暫停狀態

停止狀態
當一個活動進入到停止狀態時,與它相關聯的碎片就會進入到停止狀態,或者通過呼叫FragmentTransaction的removed(),replace()方法將碎片從活動中移除,但如果在事務提交之前呼叫addToBackStack()方法,這時碎片就會進入到停止狀態。總的來說,進入停止狀態的碎片對使用者來說是完全不可見的,有可能會被系統回收。

銷燬狀態
碎片總是依附於活動而存在的,因此當活動被銷燬時,與它相關聯的碎片就會進入到銷燬狀態。或者通過呼叫FragmentTransaction的remove(),replace()方法將碎片從活動中移除,但在事務提交之前並沒有呼叫addToBackStack()方法,這時的碎片也會進入到銷燬狀態

onAttach():當碎片和活動建立關聯的時候呼叫
onCreateView():為碎片建立檢視(載入佈局)時呼叫
onActivityCreated():確保與碎片相關聯的活動一定已經建立完畢的時候呼叫
onDestroyView():當於碎片相關聯的檢視移除時呼叫
onDetach():當碎片和活動解除關聯的時候呼叫

5、Fragment家族常用的API

Fragment常用的三個類:
android.app.Fragment 主要用於定義Fragment

android.app.FragmentManager 主要用於在Activity中操作Fragment

android.app.FragmentTransaction 保證一些列Fragment操作的原子性,熟悉事務這個詞,一定能明白~

a、獲取FragmentManage的方式:
getFragmentManager() // v4中,getSupportFragmentManager

b、主要的操作都是FragmentTransaction的方法
FragmentTransaction transaction = fm.benginTransatcion();//開啟一個事務

transaction.add()
往Activity中新增一個Fragment

transaction.remove()
從Activity中移除一個Fragment,如果被移除的Fragment沒有新增到回退棧(回退棧後面會詳細說),這個Fragment例項將會被銷燬。

transaction.replace()
使用另一個Fragment替換當前的,實際上就是remove()然後add()的合體~

transaction.hide()
隱藏當前的Fragment,僅僅是設為不可見,並不會銷燬

transaction.show()
顯示之前隱藏的Fragment

6.Fragment與Activity通訊方式
1.直接在一個Fragment中呼叫另外一個Fragment中的方法
我們可以直接在一個Fragment中呼叫另外一個Fragment的公開方法,前提是要先拿到另外一個Fragment的例項,我們先來看看怎樣在左邊的Fragment中拿到右邊Fragment的例項:

[java] view plain copy print?
ContentFragment cf = (ContentFragment) getActivity()  
                            .getFragmentManager().findFragmentById(  
                                    R.id.content_fg);  
                    cf.showPro(name);  

我們通過宿主Activity拿到FragmentManager,進而再拿到右邊的Fragment,然後呼叫右邊Fragment裡邊的showPro方法,其中要傳入的引數是左邊點選的人名,我們看看右邊Fragment中的showPro方法:

[java] view plain copy print?
public void showPro(String key) {  
    list = map.get(key);  
    adapter = new ArrayAdapter<String>(getActivity(),  
            android.R.layout.simple_list_item_1, list);  
    lv.setAdapter(adapter);  
}  

先根據傳進來的人名拿到該人作品的資料集,然後構造一個adapter賦值給listview,很簡單吧。使用這種方式我們可以直接在一個Fragment中呼叫另一個Fragment的公開方法,從而實現兩個Fragment的通訊。
這種方法適於那些我們在佈局檔案中就已經定義了的Fragment,這種Fragment每個都有id,可以通過FragmentManager找到,但是如果我們使用了ViewPager,即每個Fragment都是動態新增進來的,這個時候我們無法通過FragmentManager獲得另外一個Fragment的例項,那麼該怎麼辦呢?這時我們就要用到下面這種方式了。
2.使用介面
介面可以實現兩個Fragment之間的通訊,也可以實現Fragment和Activity之間的通訊,這大概是用的比較多的一種方式,也是個人比較推薦的一種方式,使用介面來實現兩個Fragment之間通訊,要通過宿主Activity中轉一下,如果是Fragment和宿主Activity通訊則直接呼叫即可,我們先看看上圖中點選韓愈的時候怎麼出現他的作品。首先在左邊的Fragment中定義一個介面:

[java] view plain copy print?
public interface showPro {  
    public void showProByName(String name);  
}  

然後定義一個介面變數:

[java] view plain copy print?
private showPro mCallback;  

我們要在宿主Activity中實現這個介面,這樣當Fragment呼叫onAttach方法時我們就可以例項化這個介面了:

[java] view plain copy print?
@Override  
public void onAttach(Activity activity) {  
    super.onAttach(activity);  
    if (activity != null) {  
        mCallback = (showPro) activity;  
    }  
}  

當mCallback例項化之後,那麼我們在點選韓愈的時候就可以呼叫這裡邊的showProByName方法了:

[java] view plain copy print?
lv.setOnItemClickListener(new OnItemClickListener() {  

    @Override  
    public void onItemClick(AdapterView<?> parent, View view,  
            int position, long id) {  
        TextView nameTV = (TextView) view;  
        String name = nameTV.getText().toString();  
        if ("韓愈".equals(name)) {  
            mCallback.showProByName(name);  
        }  
    }  
});  

當然,這個方法的具體實現在宿主Activity中,當宿主Activity實現了showPro介面之後,接著就要實現它裡邊的方法了:

[java] view plain copy print?
public class MainActivity extends Activity implements showPro {  

    private ContentFragment cf;  

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        getActionBar().hide();  
        cf = (ContentFragment) getFragmentManager().findFragmentById(  
                R.id.content_fg);  
    }  

    @Override  
    public void showProByName(String name) {  
        cf.showPro(name);  
    }  
}  

我們在介面的方法中呼叫右邊Fragment中的showPro方法,並將當前人名作為引數傳入,這個方法與1中相同,我就不貼程式碼了。這個方法與1中介紹的方法相比,雖然有點麻煩,但是可以有效的解決在一個Fragment中拿不到另一個Fragment例項的問題,具體應用場景就是ViewPager中的Fragment之間通訊。

3.使用廣播
不論我們有沒有用ViewPager,都可以用廣播實現兩個Fragment之間的通訊,廣播算是這裡最靈活的通訊方式了,我們看看在左邊Fragment中傳送廣播:

[java] view plain copy print?
Intent intent = new Intent("showPro");  
                    intent.putExtra("name", name);  
                    LocalBroadcastManager.getInstance(getActivity())  
                            .sendBroadcast(intent);  

在右邊Fragment中接收廣播:

[java] view plain copy print?
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager  
        .getInstance(getActivity());  
IntentFilter intentFilter = new IntentFilter();  
intentFilter.addAction("showPro");  
BroadcastReceiver br = new BroadcastReceiver() {  

    @Override  
    public void onReceive(Context context, Intent intent) {  
        String key = intent.getStringExtra("name");  
        list = map.get(key);  
        adapter = new ArrayAdapter<String>(getActivity(),  
                android.R.layout.simple_list_item_1, list);  
        lv.setAdapter(adapter);  
    }  

};  
localBroadcastManager.registerReceiver(br, intentFilter);  

這些都是廣播基本的使用方法,我就不囉嗦了。

個人覺得,雖然廣播用起來最方便,但是在選擇使用哪種通訊方式的時候,優先選擇上面兩種,如果前兩種方式都不可以,再考慮使用廣播。

4.Fragment直接呼叫Activity中的public方法
我們也可以直接在Fragment中呼叫Activity中的公開方法,如下:

[java] view plain copy print?
((MainActivity) getActivity()).showProByName(name);  

這裡的showProByName就是我們上文貼出來的那個MainActivity中的方法。