1. 程式人生 > >Android Fragment切換解決方案之FragmentTransaction

Android Fragment切換解決方案之FragmentTransaction

fragment切換?不就是Viewpager+fragment嗎?是的這是很大多數App採用的切換的組合方式。但是Viewpager+fragment切換的的生命週期十分混亂,這就是會引發很多的坑!如果在一些不需要切換的動畫的情況下,採用FragmentTransaction動態切換是一個不錯的選擇

先來看看有哪些切換的方案吧。又有哪些問題:
(一)預先寫在佈局裡面
佈局檔案

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/activity_bg" android:orientation="vertical" > <fragment android:id="@+id/fragement_main" android:name="net.loonggg.fragment.FragmentMain" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_weight="10" /> <fragment android:id="@+id/fragement_search" android:name="net.loonggg.fragment.FragmentSearch" android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="10" /> <fragment android:id="@+id/fragement_setting" android:name="net.loonggg.fragment.FragmentSetting" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="10" />

java檔案:

mFragments[0] = fragmentManager.findFragmentById(R.id.fragement_main);  
        mFragments[1] = fragmentManager.findFragmentById(R.id.fragement_search);  
        mFragments[2] = fragmentManager  
                .findFragmentById(R.id.fragement_setting);  
        fragmentTransaction = fragmentManager.beginTransaction()  
                .hide(mFragments[0]).hide(mFragments[1]).hide(mFragments[2]);  
        fragmentTransaction.show(mFragments[0]).commit();

這種方案的問題就是在如果我的某個Fragment更換了,改動的涉及到兩個檔案,而且也不能進行動態載入,侷限性比較大。

(二)Replace替換

private void replaceFragment(Fragment newFragment) {

       FragmentTransaction trasection = getFragmentManager().beginTransaction();
       try {
           //FragmentTransaction trasection =
           getFragmentManager().beginTransaction();
           trasection.replace(R.id.linearLayout2, newFragment);
           trasection.addToBackStack(null);
           trasection.commit();

       } catch (Exception e) {
           // TODO: handle exception

       }
   }

這樣總沒問題了吧?這種方案的問題在於每次呼叫replace方法時Fragment的生命週期會重走。這在現實開發中是不允許的。

解決方案:

Activity
以下采用的方式是預先將Fragment加入集合中,切換時從集合取出Fragment新增到FragmentTransaction事物中,每次加入的時候判斷是否已經新增到FragmentTransaction中,存在則呼叫show,並將上一個fragment隱藏。

public class MainActivity extends FragmentActivity implements View.OnClickListener {
    private LinearLayout tab1, tab2, tab3;
    private int currentIndex = 0;
    private ArrayList<Fragment> fragmentArrayList;
    private Fragment mCurrentFrgment;

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


    private void initView() {
        tab1 = (LinearLayout) findViewById(R.id.tab1);
        tab1.setOnClickListener(this);
        tab1.setTag(0);

        tab2 = (LinearLayout) findViewById(R.id.tab2);
        tab2.setOnClickListener(this);
        tab2.setTag(1);

        tab3 = (LinearLayout) findViewById(R.id.tab3);
        tab3.setOnClickListener(this);
        tab3.setTag(2);
    }

    private void initFragment() {
        fragmentArrayList = new ArrayList<Fragment>(3);
        fragmentArrayList.add(new Tab1Fragment());
        fragmentArrayList.add(new Tab2Fragment());
        fragmentArrayList.add(new Tab3Fragment());

        tab1.setSelected(true);
        changeTab(0);
    }


    @Override
    public void onClick(View v) {
        changeTab((Integer) v.getTag());

    }

    private void changeTab(int index) {
        currentIndex = index;
        tab1.setSelected(index == 0);
        tab2.setSelected(index == 1);
        tab3.setSelected(index == 2);

        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        //判斷當前的Fragment是否為空,不為空則隱藏
        if (null != mCurrentFrgment) {
            ft.hide(mCurrentFrgment);
        }
        //先根據Tag從FragmentTransaction事物獲取之前新增的Fragment
        Fragment fragment = getSupportFragmentManager().findFragmentByTag(fragmentArrayList.get(currentIndex).getClass().getName());

        if (null == fragment) {
            //如fragment為空,則之前未新增此Fragment。便從集合中取出
            fragment = fragmentArrayList.get(index);
        }
        mCurrentFrgment = fragment;

        //判斷此Fragment是否已經新增到FragmentTransaction事物中
        if (!fragment.isAdded()) {
            ft.add(R.id.fragment, fragment, fragment.getClass().getName());
        } else {
            ft.show(fragment);
        }
        ft.commit();
    }
}

fragment

public class Tab1Fragment extends Fragment {


    public Tab1Fragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_tab1, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        final ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.progressbar);
        final TextView tv = (TextView) view.findViewById(R.id.tv);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                progressBar.setVisibility(View.GONE);
                tv.setVisibility(View.VISIBLE);
            }
        }, 2000);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }
}

這樣做的好處是,每個Fragment切換隻進行一次初始化。