🎭 FragmentManager:木偶戏幕后的魔法操控师 🎭

101 阅读3分钟

从前有一座神奇的木偶剧场,里面有一位神秘的操控师 (FragmentManager)。他坐在幕后的控制台前,通过一套复杂的提线系统,精准控制着舞台上所有木偶 (Fragment) 的一举一动。

🌟 第一幕:剧场准备 (FragmentManager 初始化)

java

// Activity中的FragmentManager初始化
public class PuppetTheaterActivity extends AppCompatActivity {
    private FragmentManager mFragmentManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_theater);
        
        // 获取木偶操控师
        mFragmentManager = getSupportFragmentManager();
    }
}

🎤 第二幕:木偶入库 (FragmentManager 存储 Fragment)

操控师有一个巨大的木偶仓库,用哈希表存储所有木偶:

java

// FragmentManagerImpl.java (源码简化版)
class FragmentManagerImpl {
    private final ArrayMap<String, Fragment> mActiveFragments = new ArrayMap<>();
    private final ArrayMap<String, BackStackRecord> mBackStack = new ArrayMap<>();
    
    // 将木偶放入仓库
    void addFragment(Fragment fragment) {
        mActiveFragments.put(fragment.mWho, fragment);
        fragment.mFragmentManager = this;
    }
}

🎬 第三幕:提线操控 (FragmentTransaction)

当需要表演时,操控师会创建一个提线方案 (Transaction):

java

// 老板要求更换木偶
mFragmentManager.beginTransaction()
    .replace(R.id.stage_container, new ComedyPuppetFragment())
    .addToBackStack("comedy_scene")
    .commit();

// 对应的源码实现 (BackStackRecord.java)
@Override
public FragmentTransaction commit() {
    return commitInternal(false);
}

int commitInternal(boolean allowStateLoss) {
    // ... 省略部分代码
    
    // 将提线方案加入队列
    mManager.enqueueAction(this, allowStateLoss);
    return mIndex;
}

⏯️ 第四幕:执行提线方案 (FragmentManager 执行 Transaction)

java

// FragmentManagerImpl.java
void enqueueAction(Runnable action, boolean allowStateLoss) {
    synchronized (this) {
        // 将提线方案放入队列
        mPendingActions.add(action);
        
        // 安排执行时间
        if (!mExecutingActions) {
            mHost.getHandler().post(mExecCommit);
        }
    }
}

// 执行所有待处理的提线方案
private void execPendingActions() {
    // 循环处理所有Transaction
    while (!mPendingActions.isEmpty()) {
        Runnable action = mPendingActions.remove(0);
        action.run();
    }
}

🎭 第五幕:木偶状态机 (Fragment 状态管理)

操控师通过精确的状态机控制木偶的生命周期:

java

// Fragment.java 中的状态定义
public class Fragment {
    static final int INITIALIZING = 0;     // 木偶在盒子里
    static final int CREATED = 1;          // 木偶被取出盒子
    static final int ACTIVITY_CREATED = 2; // 木偶穿上表演服装
    static final int VIEW_CREATED = 3;     // 木偶安装上五官
    static final int STARTED = 4;          // 木偶被摆上舞台
    static final int RESUMED = 5;          // 木偶开始表演
    
    int mState = INITIALIZING;
    
    // 操控师调用此方法改变木偶状态
    void moveToState(int newState) {
        if (mState == newState) return;
        
        // 根据状态变化,触发相应的生命周期方法
        if (newState > mState) {
            // 状态前进 (如 STARTED → RESUMED)
            if (mState < STARTED && newState >= STARTED) {
                performStart(); // 调用onStart()
            }
            if (mState < RESUMED && newState >= RESUMED) {
                performResume(); // 调用onResume()
            }
        } else {
            // 状态后退 (如 RESUMED → STARTED)
            if (mState >= RESUMED && newState < RESUMED) {
                performPause(); // 调用onPause()
            }
            if (mState >= STARTED && newState < STARTED) {
                performStop(); // 调用onStop()
            }
        }
        
        mState = newState;
    }
}

🎪 第六幕:舞台管理 (FragmentManager 管理视图)

操控师通过舞台控制器 (Container) 管理木偶的舞台位置:

java

// FragmentManagerImpl.java
void addFragmentToContainer(Fragment fragment, ViewGroup container) {
    if (container != null) {
        // 将木偶(视图)添加到舞台上
        container.addView(fragment.getView());
    }
    
    // 更新木偶状态
    fragment.onViewCreated(fragment.getView(), null);
    fragment.moveToState(Fragment.VIEW_CREATED);
}

🕹️ 第七幕:回退栈魔法 (BackStackRecord)

操控师有一个神奇的卷轴 (BackStack),记录所有表演场景:

java

// BackStackRecord.java
@Override
public void run() {
    // 执行添加/替换/移除木偶的操作
    executeOps();
    
    // 将当前场景记录到卷轴
    if (mAddToBackStack) {
        mManager.addToBackStack(this);
    }
}

// FragmentManagerImpl.java
void addToBackStack(BackStackRecord record) {
    mBackStack.add(record.getName(), record);
}

// 用户按下返回键时
boolean popBackStackImmediate() {
    if (mBackStack.isEmpty()) return false;
    
    // 从卷轴读取上一个场景
    BackStackRecord lastRecord = mBackStack.removeLast();
    lastRecord.executeOpsInReverse(); // 反向执行操作
    return true;
}

🧠 关键概念解析

  1. FragmentManager 是幕后操控者

    • 它负责存储、管理和控制所有 Fragment
    • 使用mActiveFragments哈希表跟踪所有活动的 Fragment
  2. Transaction 是提线方案

    • 每次对 Fragment 的操作 (add/replace/remove) 都封装在 Transaction 中
    • Transaction 通过队列机制串行执行,保证线程安全
  3. 状态机驱动生命周期

    • Fragment 的生命周期由状态机严格控制
    • 每个状态变化都会触发相应的生命周期方法
  4. 回退栈实现导航

    • 回退栈就像一本场景记录册,允许操控师回放历史场景
    • 每次调用addToBackStack()都会记录当前操作

🌟 总结:FragmentManager 的魔法

FragmentManager 就像一位技艺精湛的木偶操控师,通过精确的提线系统 (FragmentTransaction)、状态机 (Fragment 状态管理) 和舞台控制器 (视图管理),让所有木偶 (Fragment) 在舞台 (Activity) 上有序表演。理解这些底层机制,就能轻松驾驭 Fragment 的复杂世界啦!

希望这个童话比喻能帮助你记住这些复杂的概念!如果有任何疑问,可以随时提问哦~😊