Fragment

Fragment源码分析!

FragmentActivity

  • BaseFragmentActivityDonut:抽象类,直接继承Activity,它的主要作用是定义了抽象方法:
    abstract View dispatchFragmentsOnCreateView(View parent, String name,
              Context context, AttributeSet attrs);
    
  • BaseFragmentActivityHoneycomb:它主要是重写了BaseFragmentActivityDonut的onCreateView方法,针对SDN_INT>=11做不同的处理。
  • ActionBarActivity:已废弃
  • AppCompatActivity 这两个及时功能上一样的,AppCompatActivity其实是在FragmentActivity上增加了ActionBar而已。

几个核心类

  • FragmentActivity:它主要是负责与Activity生命周期事件的分发。
  • FragmentController:上面的分发会传递给这个类,而它也不是实际的操作者,简单来说,它是负责继续将生命周期的操作分发给它持有的FragmentHostCallback中的FragmentManager。
  • FragmentHostCallback:它持有FragmentActivity的Activity、Context、Handler等引用,为它所持有的FragmentManager提供资源。
  • HostCallbacks:是FragmentActivity的内部类,继承FragmentHostCallback。
  • FragmentManager:只是个抽象类
  • FragmentManagerImpl FragmentManagerImpl是FragmentManager的具体实现类。它可以说是Fragment生命周期管理最重要的类

从使用分析

如何将fragment添加进来?

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(android.R.id.primary, new MyFragment());
ft.commitAllowingStateLoss();

1、getSupportFragmentManager

这里是为了获得FragmentManager对象。 最终是FragmentManagerImpl类返回的。

mFragments.getSupportFragmentManager()

FragmentActivity里的这个mFragments成员变量是如此定义的:

final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

而内部类HostCallbacks是这样的:

class HostCallbacks extends FragmentHostCallback<FragmentActivity>

这样,就把它持有FragmentActivity的Activity、Context、Handler等引用注入到了FragmentController里,即成员变量mHost

2、beginTransaction

public FragmentTransaction beginTransaction() {
     return new BackStackRecord(this);
}


BackStackRecord就是负责fragment的添加,删除,隐藏,显示等。
它维护了一个双向链表OP:记录了命令类型,以及执行命令时的动画(分为push和pop动画),以及涉及到的相关的Fragment(比如replace方法,就涉及两个Fragment)

static final class Op {
     Op next;
     Op prev;
     int cmd;
     Fragment fragment;
     int enterAnim;
     int exitAnim;
     int popEnterAnim;
     int popExitAnim;
     ArrayList<Fragment> removed;
}

3、replace or add

fragment的添加或替换只是BackStackRecord的双向链表的操作,最终都是会走到addOP()方法上。

void addOp(Op op) {
    if (mHead == null) {
        mHead = mTail = op;
    } else {
        op.prev = mTail;
        mTail.next = op;
        mTail = op;
    }
    op.enterAnim = mEnterAnim;
    op.exitAnim = mExitAnim;
    op.popEnterAnim = mPopEnterAnim;
    op.popExitAnim = mPopExitAnim;
    mNumOp++;
}

4、commit or commitAllowingStateLoss

run里针对不同的指令完成不同的FragmentManager方法的调用:

static final int OP_NULL = 0;
static final int OP_ADD = 1;
static final int OP_REPLACE = 2;
static final int OP_REMOVE = 3;
static final int OP_HIDE = 4;
static final int OP_SHOW = 5;
static final int OP_DETACH = 6;
static final int OP_ATTACH = 7;

moveToState里发起fragment状态的修改,fragment的状态分为如下:

static final int INITIALIZING = 0;     // Not yet created.
static final int CREATED = 1;          // Created.
static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.
static final int STOPPED = 3;          // Fully created, not started.
static final int STARTED = 4;          // Created and started, not resumed.
static final int RESUMED = 5;          // Created started and resumed.

最低值是INITIALIZING状态,代表fragment刚创建,还未被add, 最高状态值是RESUMED,代表fragment处于前台。 所以moveToState内部分两条线,状态跃升,和状态降低,里面各有一个switch判断,注意到switch里每个case都没有break,这意味着,状态可以持续变迁,比如从INITIALIZING,一直跃升到RESUMED,将每个case都走一遍,每次case语句内,都会改变state的值。

Fragment栈的问题

public void onBackPressed() {
    if (!mFragments.getSupportFragmentManager().popBackStackImmediate()) {
         supportFinishAfterTransition();    
    }
}

results matching ""

    No results matching ""