手把手,嘴對嘴,Fragment使用

這裏使用v4.app.Fragment ,因爲他兼容更低版本 ,他需要你的Activity繼承FragmentActivity而不是Activity ,除非你使用的是app.Fragmetn,app.Fragment兼容的最低版本爲3.0。

Fragmetn生命週期

先看下Fragment的生命週期:

這是我盜的圖

下面用代碼說話:

public class FragmentA extends android.support.v4.app.Fragment{

    /**
     * 當Fragment與Activity發生關聯時調用。
     *
     * @param context 當前Activity的Context
     */
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        L("onAttach");
    }

    /**
     * 在創建fragment時系統會調用此方法。
     * 在實現代碼中,你可以初始化想要在fragment中保持的那些必要組件(這裏的組件是指除了view之外的東西,比如需要進行界面展示的關鍵數據)
     * 當fragment處於暫停或者停止狀態之後可重新啓用它們。
     *
     * @param savedInstanceState 如果你在onSaveInstanceState()將一些值保存到了Bundle中,在這裏你可以拿到他
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String aaa = "";
        if (savedInstanceState != null)
            aaa = savedInstanceState.getString("aaa");
        L("onCreate _ " + aaa);
    }

    /**
     * 在第一次爲fragment繪製用戶界面時系統會調用此方法
     * 爲fragment繪製用戶界面,這個函數必須要返回所繪出的fragment的根View
     * 如果fragment沒有用戶界面可以返回空。
     *
     * @param inflater 用來填充的Layout
     * @param container 父容器
     * @param savedInstanceState 如果你在onSaveInstanceState()將一些值保存到了Bundle中,在這裏你可以拿到他
     * @return
     */
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        String aaa = "";
        if (savedInstanceState != null)
            aaa = savedInstanceState.getString("aaa");
        L("onCreateView _ " + aaa);
        return inflater.inflate(R.layout.fragment_a , container , false);
    }

    /**
     * 當Activity的onCreate方法返回時調用
     *
     * @param savedInstanceState 如果你在onSaveInstanceState()將一些值保存到了Bundle中,在這裏你可以拿到他
     */
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        String aaa = "";
        if (savedInstanceState != null)
            aaa = savedInstanceState.getString("aaa");
        L("onActivityCreated _ " + aaa);
    }

    /**
     *  將當前Fragment切到後臺再切回來的時候,如果這期間時間不長,他將會被第一個調用
     */
    @Override
    public void onStart() {
        super.onStart();
        L("onStart");
    }

    /**
     * 將當前Fragment切到後臺再切回來的時候,如果這期間時間不長,他將會被第二個調用
     */
    @Override
    public void onResume() {
        super.onResume();
        L("onResume");
    }

    /**
     * 系統回調用該函數作爲用戶離開fragment的第一個預兆(儘管這並不總意味着fragment被銷燬)
     * 在當前用戶會話結束之前,通常要在這裏提交任何應該持久化的變化(因爲用戶可能不再返回)。
     */
    @Override
    public void onPause() {
        super.onPause();
        L("onPause");
    }

    /**
     * 在onPause之後調用,在這裏你可以將當前Fragment的狀態保存下來,
     * 因爲用戶可能會在這個Fragment被回收之後纔回來,爲了確保他們回來後看到的界面依然是離開前的樣子
     * 你需要保存一些數據信息到Bundle,並在onCreateView()中重新設置到界面上
     * @param outState
     */
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("aaa", "FragmentA_Bundle");
        L("onSaveInstanceState");
    }

    /**
     * 半死不活
     */
    @Override
    public void onStop() {
        super.onStop();
        L("onStop");
    }

    /**
     * 這個還不太明白什麼意思……
     */
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        L("onDestroyView");
    }

    /**
     * 這個Fragment已經死透了
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        L("onDestroy");
    }

    /**
     * 這個Fragment已經跟Activity斷絕關係了
     */
    @Override
    public void onDetach() {
        super.onDetach();
        L("onDetach");
    }

    /**
     * 這是個LOG……
     * @param msg 你想說的話……
     */
    private void L(String msg){
        Log.i("FragmentTag" , "FragmentA : "  + msg);
    }

}

我將每一個生命週期的回調都打上了LOG。然後我是這麼操作的:打開App,Fragment一張傻臉呈現在我面前,然後我趕緊按返回鍵退出App。LOG信息就是下面這樣了。
onAttach
onCreate
onCreateView
onActivityCreated
onStart
onResume
onPause
onSaveInstanceState
onStop
onDestroyView
onDestroy
onDetach

具體每個回調的調用時機,都在註釋中。這裏要說的是, 如果你看到Fragment的傻臉時候按Home鍵,他會調用onPause ,onSaveInstanceState , onStop , 然後再回到他那張傻臉的時候會調用onStart , onResume。如果在這期間作了別的操作,比如說瀏覽了一些黃圖,搖了幾個妹子,然後再回來他大概已經被回收了,這時他會調用onCreate,onCreateView,onActivityCreated,onStart,onResume,我理解的是你可以在onCreateView()中通過Bundle將界面恢復到用戶離開之前的樣子。


Fragment切換

對Fragment的管理,中國人兒歪果仁兒都使用FragmentManager,通過他可以得到一個FragmentTransaction,字面意思就是事務,在對Fragment做了一系列操作後,提交事務你的操作就會或報錯或改變或沒反應的在屏幕上應驗。

首先要了解一下FragmentTransaction的這4個方法:

add() 添加

replace() 替換

hide() 隱藏

show() 顯示

英語6級不黑不吹~這裏先這樣,後面會告訴你他們怎麼用。

這裏主要說Fragment之間的切換,兩種方式:
1 . 替換 replace()
2 . 切換 hide() add() show()
看需求而定,如果Fragment之間的切換並不是特別頻繁,那麼使用1.替換會更好一點。如果你是頻繁切換,2.切換會性能更優。

這個MainActivity中,使用了“1.替換”的方式切換Fragment:

/**
 * 界面上有兩個Button
 * 點擊A切換到FragmentA
 * 點擊B切換到FragmentB
 */
public class MainActivity extends FragmentActivity {

    Fragment fragmentA;
    Fragment fragmentB;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragmentA = new FragmentA();
        fragmentB = new FragmentB();
    }

    /**
     * ButtonA的點擊事件
     * @param view
     */
    public void A(View view){
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.f , fragmentA).commit();
    }

    /**
     * ButtonB的點擊事件
     * @param view
     */
    public void B(View view){
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.f , fragmentB).commit();
    }

}

打印Log,會發現切換期間兩個Fragment是在不停初始化的,也就是說,我乾死你我再站這,你再幹死我你再站這,有你沒我有我沒你。


在這個MainActivity中,使用了“2.切換”的方式在兩個Fragment之間跳轉,纏綿,周旋,遊走,並且
個人認爲這樣纔是Fragment之間切換的正確姿勢 ,當然,不同的體位是要根據不同喜好的人改變的,這裏同理,根據需求而定:

/**
 * 界面上有兩個Button
 * 點擊A切換到FragmentA
 * 點擊B切換到FragmentB
 */
public class MainActivity extends FragmentActivity {

    Fragment fragmentA;
    Fragment fragmentB;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragmentA = new FragmentA();
        fragmentB = new FragmentB();
    }

    /**
     * ButtonA的點擊事件
     * @param view
     */
    public void A(View view){
        hideFragment();
        showWhat(fragmentA);
    }

    /**
     * ButtonB的點擊事件
     * @param view
     */
    public void B(View view){
        hideFragment();
        showWhat(fragmentB);
    }

    private void hideFragment(){
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
        if (fragmentList != null){
            for (int i = 0; i < fragmentList.size(); i++) {
                ft.hide(fragmentList.get(i));
            }
            ft.commit();
        }
    }

    private void showWhat(Fragment fragment){
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        if (!fragment.isAdded()){
            ft.add(R.id.f, fragment);
        }else{
            ft.show(fragment);
        }
        ft.commit();
    }

}

打印Log,會發現切換期間完全沒有走任何一個生命週期,除了第一次add()的時候。這就相當於你去前臺表演的時候我就去幕後了,我們輪流上臺。說到輪流,我想起了一首詩。“南村羣童欺我老無力,輪流與我發生性關係”,哈哈哈哈哈。算福利了,送給大家。


好了 基本使用就這些了,下面還會有一些別的花樣兒等着你。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章