美文网首页
为什么要通过Fragment.setArguments(Bund

为什么要通过Fragment.setArguments(Bund

作者: 因为我的心 | 来源:发表于2023-05-16 13:38 被阅读0次

一、Fragement的方法

Fragment在开发中是经常使用的,我们在创建一个Fragment对象实例的时候一般都会通过new Fragment()构造方法来实现。如果在创建Fragment的时候需要向其传递数据,则可以通过构造方法直接来传递参数,或者通过Fragment.setArguments(Bundle bundle)这种方式来传递参数。这两种参数传递方式大概如下:

1、 方式一:通过构造方法传递参数

在创建Fragment的时候,使用 MyFragment fragment = new MyFragment(parameter) 来传递参数。

public class MyFragment extends Fragment {
    public MyFragment(String p){
        //将参数保存起来
    }
}

2、方式二:通过Fragment.setArguments(Bundle)传递参数

在创建Fragment的时候,使用MyFragment fragment = MyFragment.newInstance(paramter) 来传递参数。

public class MyFragment extends Fragment {
    public static MyFragment newInstance(Parameter p) {
        MyFragment myFragment = new MyFragment();
        Bundle args = new Bundle();
        args.putInt("someParameter", p);
        myFragment.setArguments(args);
        return myFragment;
    }
}

3、Kotlin写法

      //出入数据
      val childFragments = arrayListOf<Fragment>()
      var first = FirstFragment("第一个页面")
        val args1 = Bundle()
        args1.putString("type", "类型1")
        args1.putString("name", "小明")
        first.arguments = args1
        childFragments.add(first)

//获取数据
val type = arguments?.get("type")
val name = arguments?.get("name")
binding.textviewFirst.text = "${tabName}类型:${type} 名字:${name}"

二、对比分析

看上去这两种方式没有什么本质的区别,但是通过构造方法传递参数的方式是有隐患的。根据Android文档说明,当一个Fragment重新创建的时候,系统会再次调用Fragment中的默认构造函数,注意是默认构造函数。即,当你创建了一个带有参数的Fragment的之后,一旦由于什么原因(例如横竖屏切换)导致你的Fragment重新创建。那么,很遗憾,你之前传递的参数都不见了,因为recreate你的Fragment的时候,调用的是默认构造函数。因此,官方推荐使用Fragment.setArguments(Bundle bundle)这种方式来传递参数,而不推荐通过构造方法直接来传递参数。

推荐使用Fragment.setArguments(Bundle)传递参数原因

(1)Activity的onCreate(Bundle saveInstance)方法
protected void onCreate(Bundle savedInstanceState) {  
    if (DEBUG_LIFECYCLE ) Slog.v( TAG, "onCreate " + this + ": " + savedInstanceState);  
    if (mLastNonConfigurationInstances != null) {  
        mAllLoaderManagers = mLastNonConfigurationInstances .loaders ;  
    }  
    if (mActivityInfo .parentActivityName != null) {  
        if (mActionBar == null) {  
            mEnableDefaultActionBarUp = true ;  
        } else {  
            mActionBar .setDefaultDisplayHomeAsUpEnabled( true);  
        }  
    }  
    if (savedInstanceState != null) {  
        Parcelable p = savedInstanceState.getParcelable( FRAGMENTS_TAG );  
        mFragments .restoreAllState(p, mLastNonConfigurationInstances != null  
                ? mLastNonConfigurationInstances .fragments : null);  
    }  
    mFragments .dispatchCreate();  
    getApplication().dispatchActivityCreated( this , savedInstanceState);  
    mCalled = true ;  
}  
(2)跟进FragmentManager.restoreAllState()方法
  for (int i=0; i<fms.mActive.length; i++) {  
           FragmentState fs = fms.mActive[i];  
           if (fs != null) {  
              Fragment f = fs.instantiate(mActivity, mParent);  
               if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);  
               mActive.add(f);  
               // Now that the fragment is instantiated (or came from being  
               // retained above), clear mInstance in case we end up re-restoring  
                // from this FragmentState again.  
                fs.mInstance = null;  
           } else {  
               mActive.add(null);  
                if (mAvailIndices == null) {  
                    mAvailIndices = new ArrayList<Integer>();  
               }  
               if (DEBUG) Log.v(TAG, "restoreAllState: avail #" + i);  
               mAvailIndices.add(i);  
           }  
} 
(3)跟进FragmentState.instantitate()方法
public Fragment instantiate(Activity activity, Fragment parent) {  
        if (mInstance != null) {  
            return mInstance ;  
        }  
         
        if (mArguments != null) {  
            mArguments .setClassLoader(activity.getClassLoader());  
        }  
         
        mInstance = Fragment.instantiate(activity, mClassName , mArguments );  
         
        if (mSavedFragmentState != null) {  
            mSavedFragmentState .setClassLoader(activity.getClassLoader());  
            mInstance .mSavedFragmentState = mSavedFragmentState ;  
        }  
        mInstance .setIndex(mIndex , parent);  
        mInstance .mFromLayout = mFromLayout ;  
        mInstance .mRestored = true;  
        mInstance .mFragmentId = mFragmentId ;  
        mInstance .mContainerId = mContainerId ;  
        mInstance .mTag = mTag ;  
        mInstance .mRetainInstance = mRetainInstance ;  
        mInstance .mDetached = mDetached ;  
        mInstance .mFragmentManager = activity.mFragments;  
        if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,  
                "Instantiated fragment " + mInstance );  
  
        return mInstance ;  
    } 

(4)最终转入到Fragment.instantitate()方法

参考链接:https://www.jianshu.com/p/c06efe090589

相关文章

网友评论

      本文标题:为什么要通过Fragment.setArguments(Bund

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