1. 程式人生 > >fragment不重新例項化

fragment不重新例項化

關於Fragment

在這簡單說一下Fragment,Fragment是Android 3.0以後才出現的,是為了適應不同的手機螢幕、平板和電視機的螢幕的。另外還有一個重要的原因,因為Activity的建立到銷燬需要費時費記憶體,大量的Activity之間的跳轉會造成堆疊飽滿,引發程式崩潰或者無響應。為了解決這個問題,Fragment就產生了。Fragment是通過Activity的FragmentManager管理的,並且一個Activity可以管理多個Fragment,有效的解決了大量Activity造成的堆疊飽滿問題。現在幾乎每一個安卓App裡面都用到了Fragment。

動態新增Fragment

首先你要有一個Fragment的載體,我是用幀佈局FrameLayout作為載體。

佈局檔案:

avtivity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width
="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.sonnyzoom.fragmentdemo.MainActivity">
<android.support.v7.widget.Toolbar android:id="@+id/toolBar" android:layout_width="match_parent" android:layout_height
="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" />
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="3" android:background="#CEE" android:orientation="vertical"> <Button android:id="@+id/btn_one" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="one" /> <Button android:id="@+id/btn_two" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="two" /> </LinearLayout> <FrameLayout android:id="@+id/content" android:background="#EEE" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout> </LinearLayout>

然後在Activity中:

FragmentManager fragmentManager=getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content,new FragmentOne()).commit();

這樣就可以把Fragment動態新增到佈局裡面了。我們看一下效果:


重新例項化.gif


大家有沒有發現,原來的Fragment裡的資料會隨著Fragment的切換而丟失了,也就是切換Fragment後再切換回來的話,前一個Fragment會被重新例項化,當然介面的資料也沒了。為什麼呢?重點來了。

解決Fragment重新例項化

如果每切換一次就例項化一次的話,FragmentManager管理下的棧也會爆滿,最終會導致手機卡頓,這很明顯不是正確的Fragment使用姿勢。正確的姿勢是使用Fragment提供的事務FragmentTransaction,然後用add的方法,而不是每次都用replace。
獲取FragmentTransaction物件:

FragmentTransaction ft=fragmentManager.beginTransaction();

然後判斷一下Fragment物件是否為空,不為空的話就用ft的hide方法把Fragment隱藏起來。不然會出現佈局重疊的情況。

    public void hideFragment(FragmentTransaction ft){
        //如果不為空,就先隱藏起來
        if (oneFm!=null){
            ft.hide(oneFm);
        }
        if(twoFm!=null) {
            ft.hide(twoFm);
        }
    }

接著用ft的show方法將Fragment顯示出來:

                /**
                 * 如果Fragment為空,就新建一個例項
                 * 如果不為空,就將它從棧中顯示出來
                 */
                if (oneFm==null){
                    oneFm=new FragmentOne();
                    ft.add(R.id.content,oneFm);
                }else {
                    ft.show(oneFm);
                }

好了,我們看一下效果:


解決重新例項化.gif


是不是完美解決了問題?下面貼出整個MainActivity的程式碼:

MainActivity.java
package com.sonnyzoom.fragmentdemo;

import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Toolbar toolbar;
    private Button btnOne,btnTwo;
    public FragmentManager fragmentManager;
    private FragmentOne oneFm;
    private FragmentTwo twoFm;

    public static final int FRAGMENT_ONE=0;
    public static final int FRAGMENT_TWO=1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        toolbar= (Toolbar) findViewById(R.id.toolBar);
        setSupportActionBar(toolbar);

        fragmentManager=getSupportFragmentManager();
        showFragment(FRAGMENT_ONE);

        btnOne= (Button) findViewById(R.id.btn_one);
        btnTwo= (Button) findViewById(R.id.btn_two);

        btnOne.setOnClickListener(this);
        btnTwo.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){

            case R.id.btn_one:
                showFragment(FRAGMENT_ONE);
                break;
            case R.id.btn_two:
                showFragment(FRAGMENT_TWO);
                break;

        }
    }

    public void showFragment(int index){

        FragmentTransaction ft=fragmentManager.beginTransaction();
        hideFragment(ft);

        switch (index){

            case FRAGMENT_ONE:
                toolbar.setTitle("One");
                /**
                 * 如果Fragment為空,就新建一個例項
                 * 如果不為空,就將它從棧中顯示出來
                 */
                if (oneFm==null){
                    oneFm=new FragmentOne();
                    ft.add(R.id.content,oneFm);
                }else {
                    ft.show(oneFm);
                }

                break;
            case FRAGMENT_TWO:
                toolbar.setTitle("Two");

                點選開啟連結if (twoFm==null){
                    twoFm=new FragmentTwo();
                    ft.add(R.id.content,twoFm);
                }else {
                    ft.show(twoFm);
                }

                break;
        }

        ft.commit();
    }

    public void hideFragment(FragmentTransaction ft){
        //如果不為空,就先隱藏起來
        if (oneFm!=null){
            ft.hide(oneFm);
        }
        if(twoFm!=null) {
            ft.hide(twoFm);
        }
    }

}


文/backkomyoung(簡書作者)
原文連結:http://www.jianshu.com/p/91fa45c10eb7
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。