Fragment在FrameLayout

Fragment

  • API11(Android3.0)中引入了Fragment,由FragmentManager來管理。
  • Fragment extends object 。
  • Fragment也是Activity中的一個普通控件而已,只不過它可以像Activity一樣用於顯示的同時還能用來盛裝其它控件,並且有類似Activity的lifecycle。
  • 可被多個Acitivity重用, 在Acitivity運行中動態地移除、加入、交換等。
  • 兼容API11(Android3.0)以前版本使用 v4.app.Fragment,Acitivity需要繼承AppCompatActivity,通過getSupportFragmentManager() 獲得v4.app.FragmentManager 。
  • API11(Android3.0)以後可使用 app.Fragment,通過getFragmentManager()獲得app.FragmentManager 。

生命週期lifecycle

  • 類似Acitivty,但是由Activity管理,由許多不同點。
    這裏寫圖片描述

簡單添加到Activity方法

 private void add() {
        OneFragment oneFragment = OneFragment.newInstance("");
        FragmentTransaction transaction = mManager.beginTransaction();
        transaction.add(R.id.fl_container, oneFragment, "one");
        transaction.commit();
    }
  • 將Fragment添加到Activity中,並生效。
  • 重要的類有FragmentManager 和FragmentTransaction,在下面詳細分析。

Fragment相關的類及其方法

FragmentManager

  • FragmentManager是一個抽象類, getFragmentManager()獲取的是FragmentManagerImpl ,是一個實現類
//調用層級 最後是FragmentManagerImpl 
getFragmentManager()  
  -->FragmentController(Fragment's lifecycle)
  -->getFragmentManagerImpl()
  -->FragmentHostCallback 
  -->final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
  • FragmentManager.java中 定義FragmentManager /FragmentManagerImpl / FragmentManagerState三個類/接口

  • beginTransaction() 獲得FragmentTransaction,FragmentManagerImpl 中的Override的beginTransaction()

 @Override
    public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }
  • findFragmentById(@IdRes int id) 相同id ,取第一個找到的,一般就是最上面的。
  • findFragmentByTag(String tag) 相同tag,取第一個找到的,一般就是最上面的。
  • getFragments() 返回ArrayList< Fragment > mActive; 可能存在null
  • 持有一個BackStackRecord的列表 ArrayList< BackStackRecord > mBackStackIndices

FragmentTransaction

  • add 和 replace 影響的只是界面,而控制回退的,是事務

  • FragmentTransaction 是一個抽象類, beginTransaction()獲取的是BackStackRecord,是一個實現類

  • BackStackRecord extends FragmentTransaction

  • add 和 replace 影響的只是界面,而控制回退的是事務,add 和 replace最後調用addOp(Op op)
  • addOp(Op op) 添加到隊列mOps中,通過commit纔會提交

    void addOp(Op op) {
          mOps.add(op);
          op.enterAnim = mEnterAnim;
          op.exitAnim = mExitAnim;
          op.popEnterAnim = mPopEnterAnim;
          op.popExitAnim = mPopExitAnim;
      }
  • addToBackStack(將事務添加到回退棧裏)

    @Override
      public FragmentTransaction addToBackStack(String name) {
          if (!mAllowAddToBackStack) {
              throw new IllegalStateException(
                      "This FragmentTransaction is not allowed to be added to the back stack.");
          }
          mAddToBackStack = true;
          mName = name;
          return this;
      }
  • commit (提交到處理隊列裏,默認不會添加到回退棧,默認等待執行),調用commitInternal(false)

    int commitInternal(boolean allowStateLoss) {
          if (mCommitted) throw new IllegalStateException("commit already called");
          if (FragmentManagerImpl.DEBUG) {
              Log.v(TAG, "Commit: " + this);
              LogWriter logw = new LogWriter(TAG);
              PrintWriter pw = new PrintWriter(logw);
              dump("  ", null, pw, null);
              pw.close();
          }
          mCommitted = true;
          if (mAddToBackStack) {
              mIndex = mManager.allocBackStackIndex(this);
          } else {
              mIndex = -1;
          }
          mManager.enqueueAction(this, allowStateLoss);
          return mIndex;
      }
add
  • add(@IdRes int containerViewId, Fragment fragment)
  • 可能出現 Fragment already added 錯誤,原因:add 已經add的fragment(hashcode一樣)
  • lifecycle方法調用情況
10-23 17:01:58.737 13673-13673/com.wega.android E/Frag+Frame: OneFragment==null==OneFragment
10-23 17:01:58.743 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onAttach
10-23 17:01:58.744 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onCreate
10-23 17:01:58.744 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onCreateView
10-23 17:01:58.753 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onActivityCreated
10-23 17:01:58.753 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onStart
10-23 17:01:58.753 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onResume
  • 在add 前 需要new Fragment() ,但是new不會調起Framgent生命週期動作如:oncreate ,而 Acitivty不需要我們new的,是由系統創建的.
remove
  • remove(Fragment fragment)
  • Remove an existing fragment
  • 先獲得已存在fragment才能remove 不能傳空值
  • 通過findFragmentById() findFragmentByTag()獲得已存在fragment
  • lifecycle方法調用情況
10-23 17:02:55.873 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onPause
10-23 17:02:55.874 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onStop
10-23 17:02:55.874 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onDestroyView
10-23 17:02:55.874 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onDestroy
10-23 17:02:55.874 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onDetach
replace
  • replace(@IdRes int containerViewId, Fragment fragment)
  • 不能傳空值
  • 先remove掉相同id的所有fragment,然後在add當前的這個fragment
  • add 和 remove 結合
  • lifecycle方法調用情況
10-23 17:07:11.092 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==OneFragment
10-23 17:07:11.098 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onAttach
10-23 17:07:11.098 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onCreate
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==0==onPause
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==0==onStop
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==0==onDestroyView
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==0==onDestroy
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==0==onDetach
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onCreateView
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onActivityCreated
10-23 17:07:11.100 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onStart
10-23 17:07:11.100 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onResume
hide
  • hide(Fragment fragment)
  • 與show一起作用
  • hide 已經添加的fragment 不能傳空值
  • hide fragment 不會調用生命週期
show
  • show(Fragment fragment)
  • 與hide一起作用
  • This is only relevant for fragments whose views have been added to a container
  • show已經hide的fragment
  • show fragment 不會調用生命週期
detach
  • detach(Fragment fragment)
  • 與attach一起作用
  • 不能傳空值
  • lifecycle方法調用情況
10-23 17:07:41.687 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onPause
10-23 17:07:41.687 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onStop
10-23 17:07:41.687 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onDestroyView
attach

-attach(Fragment fragment)
- 與detach一起作用
- 不能傳空值
- lifecycle方法調用情況

10-23 17:07:56.420 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onCreateView
10-23 17:07:56.420 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onActivityCreated
10-23 17:07:56.421 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onStart
10-23 17:07:56.421 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onResume

重建 切屏

  • Fragment也有onSaveInstanceState的方法,在此方法中進行保存數據,然後在onCreate或者onCreateView或者onActivityCreated進行恢復都可以。
 @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putString("name", "save");
        super.onSaveInstanceState(outState);

        Log.e("Activity", TAG +"=="+mTag1+"=="+"onSaveInstanceState"+"=="+outState.getString("name"));
    }
 @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(savedInstanceState!=null)
        {
            Log.e("Activity", TAG +"=="+mTag1+"=="+"onCreate"+"=="+savedInstanceState.getString("name"));
        }
        Bundle arguments = getArguments();
        if(arguments!=null)
        {
            mTag1 = arguments.getString("tag");
        }
        Log.e("Activity", TAG +"=="+mTag1+"=="+"onCreate");
    }

demo源碼

FragmentActivity

package com.wega.android.fragment;

import android.content.DialogInterface;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import com.wega.android.R;

import java.util.List;

public class FragmentActivity extends AppCompatActivity implements View.OnClickListener {

    private String LOG_TAG="Frag+Frame";

    private FragmentManager mManager;
    private OneFragment mOneFragment;
    private String TAG;
    private int num;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment);
        mManager = getSupportFragmentManager();
        TAG = this.getClass().getSimpleName();
        if (savedInstanceState == null) {
            Log.e(LOG_TAG, TAG + "==onCreate");
        } else {

            String name = savedInstanceState.getString("name");
            Log.e(LOG_TAG, TAG + "==onCreate==name==" + name);
        }
        findViewById(R.id.add).setOnClickListener(this);
        findViewById(R.id.remove).setOnClickListener(this);
        findViewById(R.id.replace).setOnClickListener(this);
        findViewById(R.id.log).setOnClickListener(this);
        findViewById(R.id.show).setOnClickListener(this);
        findViewById(R.id.hide).setOnClickListener(this);
        findViewById(R.id.attach).setOnClickListener(this);
        findViewById(R.id.detach).setOnClickListener(this);
    }


    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.add:
                add();
                break;
            case R.id.remove:
                remove();
                break;
            case R.id.replace:
                replace();
                break;
            case R.id.show:
                show();
                break;
            case R.id.hide:
                hide();
                break;
            case R.id.log:
                getFragmentList();
                break;
            case R.id.attach:
                attach();
                break;
            case R.id.detach:
                detach();
                break;
        }
    }



    private void add() {

        OneFragment oneFragment = OneFragment.newInstance("" + num++);
        FragmentTransaction transaction = mManager.beginTransaction();
        transaction.add(R.id.fl_container, oneFragment, "one");
        transaction.commit();
    }


    private void remove(){
        Fragment fragmentById = mManager.findFragmentById(R.id.fl_container);
        FragmentTransaction transaction = mManager.beginTransaction();
        if(fragmentById!=null)
        {
            transaction.remove(fragmentById);
        }
        transaction.commit();
    }


    private void replace() {

        if (mOneFragment == null) {
            mOneFragment = new OneFragment();
        }
        FragmentTransaction transaction = mManager.beginTransaction();
        transaction.replace(R.id.fl_container, mOneFragment);
        transaction.commit();

    }


    private void show() {
        Fragment fragmentById = mManager.findFragmentById(R.id.fl_container);
        FragmentTransaction transaction = mManager.beginTransaction();
        transaction.show(fragmentById);
        transaction.commit();
    }


    private void hide() {
        Fragment fragmentById = mManager.findFragmentById(R.id.fl_container);
        FragmentTransaction transaction = mManager.beginTransaction();
        transaction.hide(fragmentById);
        transaction.commit();
    }

    private void attach() {
        Fragment fragmentById = mManager.findFragmentById(R.id.fl_container);
        FragmentTransaction transaction = mManager.beginTransaction();
        transaction.attach(fragmentById);
        transaction.commit();
    }

    private void detach() {
        Fragment fragmentById = mManager.findFragmentById(R.id.fl_container);
        FragmentTransaction transaction = mManager.beginTransaction();
        transaction.detach(fragmentById);
        transaction.commit();
    }

    private void getFragmentList() {
        Fragment fragment = mManager.findFragmentById(R.id.fl_container);
        Fragment fragment1 = mManager.findFragmentByTag("one");
        if (fragment != null) {
            Log.e("fragment", "findFragmentById=" + fragment.toString());
        }

        if (fragment1 != null) {
            Log.e("fragments1", "findFragmentByTag=" + fragment1.toString());
        }

        List<Fragment> fragments = mManager.getFragments();
        if (fragments == null) {
            return;
        }

        for (int i = 0; i < fragments.size(); i++) {

            if (fragments.get(i) == null) {
                Log.e("fragments", "null");
            } else {
                Log.e("fragments", fragments.get(i).toString());
            }

        }
        Log.e("fragments", "==========");

    }

}

OneFragment

package com.wega.android.fragment;


import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.wega.android.R;


/**
 * A simple {@link Fragment} subclass.
 */
public class OneFragment extends Fragment {


    private String TAG;
    private String LOG_TAG="Frag+Frame";
    private String mTag1;

    public OneFragment() {
        TAG =this.getClass().getSimpleName();
        Bundle arguments = getArguments();
        if(arguments!=null)
        {
            mTag1 = arguments.getString("tag");
        }
        Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"OneFragment");
    }

    public static OneFragment newInstance(String tag) {

        Bundle args = new Bundle();
        args.putString("tag",tag);
        OneFragment fragment = new OneFragment();
        fragment.setArguments(args);
        return fragment;
    }




    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Bundle arguments = getArguments();
        if(arguments!=null)
        {
            mTag1 = arguments.getString("tag");
        }
        Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onAttach");
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(savedInstanceState!=null)
        {
            Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onCreate"+"=="+savedInstanceState.getString("name"));
        }
        Bundle arguments = getArguments();
        if(arguments!=null)
        {
            mTag1 = arguments.getString("tag");
        }
        Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onCreate");

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        TAG =this.getClass().getSimpleName();
        Bundle arguments = getArguments();
        if(arguments!=null)
        {
            mTag1 = arguments.getString("tag");
        }
        Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onCreateView");
        View inflate = inflater.inflate(R.layout.fragment_one, container, false);
        TextView viewById = (TextView) inflate.findViewById(R.id.tv_hashcode);
        viewById.setText(this.toString()+"tag=="+mTag1);
        return inflate;
    }


    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onActivityCreated");
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onStart");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onResume");
    }


    @Override
    public void onPause() {
        super.onPause();
        Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onPause");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onStop");
    }


    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onDestroyView");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onDestroy");
    }


    @Override
    public void onDetach() {
        super.onDetach();
        Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onDetach");
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putString("name", "save");
        super.onSaveInstanceState(outState);

        Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onSaveInstanceState"+"=="+outState.getString("name"));
    }



}

demo源碼地址

github demo源碼地址:https://github.com/LinweiJ/Android

backStack

未完待續

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