美文网首页
FragmentActivity如何控制Fragment的创建销

FragmentActivity如何控制Fragment的创建销

作者: 陈萍儿Candy | 来源:发表于2021-01-13 15:04 被阅读0次

在FragmentActivity添加一个fragment

 FragmentManager supportFragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
//        fragmentTransaction.add(R.id.container,new ChatFragment());
        fragmentTransaction.replace(R.id.container,new ChatFragment());
        fragmentTransaction.commit();


一。FragmentActivity中,如何控制fragment的add和remove,以及和acitivity之间的关联?
fragmentActivity中初始化一个FragmentController实例,mFragments,mFragments中传入了一个hostCallback对象,hostCallback对象中带有FragmentActivity的对象和context等信息,并初始化了
FragmentManagerImpl的对象;
在FragmentActiviy中通过调用mFragments中的方法,mFragments中的方法再调用hostCallBack.mFragmentManagerImpl中对应的方法,来控制fragment的中的方法的执行,fragment中也会通过mFragmentManagerImpl获取到hostCallback对象,自然可以获取到FragmentActivity对象和context对象;
具体源码截取如下

// 创建FragmentController对象,传入HostCallbacks对象
inal FragmentController mFragments = FragmentController.createController(new HostCallbacks());

// HostCallbacks构造方法如下,是FragmentActivity的内部类
class HostCallbacks extends FragmentHostCallback<FragmentActivity> implements
       ViewModelStoreOwner,
       OnBackPressedDispatcherOwner {
   public HostCallbacks() {
       super(FragmentActivity.this /*fragmentActivity*/);
   }

…
}

FragmentHostCallback的内部属性如下

public abstract class FragmentHostCallback<E> extends FragmentContainer {
    @Nullable private final Activity mActivity; // 持有activity的对象
    @NonNull private final Context mContext; // 持有Context的对象
    @NonNull private final Handler mHandler;
    private final int mWindowAnimations;
// 初始化FragmentManagerImpl的对象
    final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();

    public FragmentHostCallback(@NonNull Context context, @NonNull Handler handler,
            int windowAnimations) {
        this(context instanceof Activity ? (Activity) context : null, context, handler,
                windowAnimations);
    }

    FragmentHostCallback(@NonNull FragmentActivity activity) {
        this(activity, activity /*context*/, new Handler(), 0 /*windowAnimations*/);
    }

    FragmentHostCallback(@Nullable Activity activity, @NonNull Context context,
            @NonNull Handler handler, int windowAnimations) {
        mActivity = activity;
        mContext = Preconditions.checkNotNull(context, "context == null");
        mHandler = Preconditions.checkNotNull(handler, "handler == null");
        mWindowAnimations = windowAnimations;
    }
…
}

二。了解这些后,分析第一行代码:getSupportFragmentManager(),

/**
 * Return the FragmentManager for interacting with fragments associated
 * with this activity.
 */
@NonNull
public FragmentManager getSupportFragmentManager() {
    return mFragments.getSupportFragmentManager();
}

FragmentController中,是获取的host中的mFragmentManager

/**
 * Returns a {@link FragmentManager} for this controller.
 */
@NonNull
public FragmentManager getSupportFragmentManager() {
    return mHost.mFragmentManager;
}

比如:FragmentActivity中onCreateView方法

@Override
@Nullable
public View onCreateView(@NonNull String name, @NonNull Context context,
        @NonNull AttributeSet attrs) {
    final View v = dispatchFragmentsOnCreateView(null, name, context, attrs);
    if (v == null) {
        return super.onCreateView(name, context, attrs);
    }
    return v;
}

@Nullable
final View dispatchFragmentsOnCreateView(@Nullable View parent, @NonNull String name,
        @NonNull Context context, @NonNull AttributeSet attrs) {
    return mFragments.onCreateView(parent, name, context, attrs);
}

FragmentController中

@Nullable
public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context,
        @NonNull AttributeSet attrs) {
    return mHost.mFragmentManager.onCreateView(parent, name, context, attrs);
}

mFragmentManager中的onCreateView,比较长,删减了

@Override
@Nullable
public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context,
                         @NonNull AttributeSet attrs) {
    if (!"fragment".equals(name)) {
        return null;
    }

    String fname = attrs.getAttributeValue(null, "class");
    …

   
    // If we haven't finished entering the CREATED state ourselves yet,
    // push the inflated child fragment along. This will ensureInflatedFragmentView
    // at the right phase of the lifecycle so that we will have mView populated
    // for compliant fragments below.
    if (mCurState < Fragment.CREATED && fragment.mFromLayout) {
// 重点,如果fragment没有创建,开始创建,
        moveToState(fragment, Fragment.CREATED, 0, 0, false);
    } else {
        moveToState(fragment);
    }

    if (fragment.mView == null) {
        throw new IllegalStateException("Fragment " + fname
                + " did not create a view.");
    }
    if (id != 0) {
        fragment.mView.setId(id);
    }
    if (fragment.mView.getTag() == null) {
        fragment.mView.setTag(tag);
    }
    return fragment.mView;
}

moveTostate方法比较多,删减

void moveToState(Fragment f, int newState, int transit, int transitionStyle,
                 boolean keepActive) {
    。。。。
        switch (f.mState) {
            。。。
            case Fragment.CREATED:
                            。。。
                            containe = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
                            if (container == null && !f.mRestored) {
                                String resName;
                                try {
                                    resName = f.getResources().getResourceName(f.mContainerId);
                                } catch (Resources.NotFoundException e) {
                                    resName = "unknown";
                                }
                                throwException(new IllegalArgumentException(
                                        "No view found for id 0x"
                                                + Integer.toHexString(f.mContainerId) + " ("
                                                + resName
                                                + ") for fragment " + f));
                            }
                        }
                        f.mContainer = container;
                        //   重点:执行fragment的createview方法
                        f.performCreateView(f.performGetLayoutInflater(
                                f.mSavedFragmentState), container, f.mSavedFragmentState);
                        。。。。
                }
。。。。
}

Fragment中的performCreateView方法如下:

void performCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
        @Nullable Bundle savedInstanceState) {
    mChildFragmentManager.noteStateNotSaved();
    mPerformedCreateView = true;
    mViewLifecycleOwner = new FragmentViewLifecycleOwner();
// 重点:执行了onCreateView方法
    mView = onCreateView(inflater, container, savedInstanceState);
    if (mView != null) {
        // Initialize the view lifecycle
        mViewLifecycleOwner.initialize();
        // Then inform any Observers of the new LifecycleOwner
        mViewLifecycleOwnerLiveData.setValue(mViewLifecycleOwner);
    } else {
        if (mViewLifecycleOwner.isInitialized()) {
            throw new IllegalStateException("Called getViewLifecycleOwner() but "
                    + "onCreateView() returned null");
        }
        mViewLifecycleOwner = null;
    }
}

三。FragmentManager:
是个抽象类,其实现类为:FragmentManagerImpl,FragmentManagerImpl里面有final

ArrayList<Fragment> mAdded = new ArrayList<>();

final HashMap<String, Fragment> mActive = new HashMap<>();

mAdded列表是fragment被added,没有从activity中removed或者detached;

mActive列表是被added过的所有的fragment,只有以下两种情况fragment会被mActive列表中移除

1.它已经从activity中移除,并且不在backstack中。

2.一个事务从backstack弹出,并且在一个片段上的add或replace操作被detach/remove,该片段现在不再被backstack引用。

mAdded,mActive相关参考链接:https://stackoverflow.com/questions/25695960/difference-between-madded-mactive-in-source-code-of-support-fragmentmanager

1.fragmentManager,FragmentTransaction,backStackRecord三者联系

supportFragmentManager.beginTransaction();获取的是backStackRecord的实例;

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

backStackRecord是fragmentTransaction的子类

final class BackStackRecord extends FragmentTransaction implements
        FragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator

当我们调用add/或者replace方法时,是把信息组装到FragmentTrasaction的Op中,并附有操作标记,如OP_ADD等,处理Op是在backStackRecord的executeOps()方法中

/**
 * Executes the operations contained within this transaction. The Fragment states will only
 * be modified if optimizations are not allowed.
 */
void executeOps() {
    final int numOps = mOps.size();
    for (int opNum = 0; opNum < numOps; opNum++) {
        final Op op = mOps.get(opNum);
        final Fragment f = op.mFragment;
        if (f != null) {
            f.setNextTransition(mTransition, mTransitionStyle);
        }
        switch (op.mCmd) {
            case OP_ADD:
                f.setNextAnim(op.mEnterAnim);
                mManager.addFragment(f, false);
                break;
            case OP_REMOVE:
                f.setNextAnim(op.mExitAnim);
                mManager.removeFragment(f);
                break;
            case OP_HIDE:
                f.setNextAnim(op.mExitAnim);
                mManager.hideFragment(f);
                break;
            case OP_SHOW:
                f.setNextAnim(op.mEnterAnim);
                mManager.showFragment(f);
                break;
            case OP_DETACH:
                f.setNextAnim(op.mExitAnim);
                mManager.detachFragment(f);
                break;
            case OP_ATTACH:
                f.setNextAnim(op.mEnterAnim);
                mManager.attachFragment(f);
                break;
            case OP_SET_PRIMARY_NAV:
                mManager.setPrimaryNavigationFragment(f);
                break;
            case OP_UNSET_PRIMARY_NAV:
                mManager.setPrimaryNavigationFragment(null);
                break;
            case OP_SET_MAX_LIFECYCLE:
                mManager.setMaxLifecycle(f, op.mCurrentMaxState);
                break;
            default:
                throw new IllegalArgumentException("Unknown cmd: " + op.mCmd);
        }
        if (!mReorderingAllowed && op.mCmd != OP_ADD && f != null) {
            mManager.moveFragmentToExpectedState(f);
        }
    }
    if (!mReorderingAllowed) {
        // Added fragments are added at the end to comply with prior behavior.
        mManager.moveToState(mManager.mCurState, true);
    }
}

最终OP_ADD/OP_REMOVE等操作是在FragmentManagerImpl中实现具体的添加或者移除fragment的操作;具体可以看源码,不再附源码;

四。fragmentTransaction.replace/add(R.id.container,new ChatFragment());
传入的containerId,如果是0,fragment无法添加到一个容器上,无法展示,但是可以添加成功,可以做后台服务等操作;

相关文章

网友评论

      本文标题:FragmentActivity如何控制Fragment的创建销

      本文链接:https://www.haomeiwen.com/subject/tgreaktx.html