返回顶部
首页 > 资讯 > 移动开发 >Android 中为什么要用Fragment.setArguments(Bundle bundle)来传递参数
  • 774
分享到

Android 中为什么要用Fragment.setArguments(Bundle bundle)来传递参数

参数bundlefragmentAndroid 2022-06-06 04:06:18 774人浏览 泡泡鱼
摘要

Fragment在Android3.0开始提供,并且在兼容包中也提供了Fragment特性的支持。Fragment的推出让我们编写和管理用户界面更快捷更方便了。 但当我们实例化

Fragment在Android3.0开始提供,并且在兼容包中也提供了Fragment特性的支持。Fragment的推出让我们编写和管理用户界面更快捷更方便了。

但当我们实例化自定义Fragment时,为什么官方推荐Fragment.setArguments(Bundle bundle)这种方式来传递参数,而不推荐通过构造方法直接来传递参数呢?为了弄清这个问题,我们可以做一个测试,分别测试下这两种方式的不同

首先,我们来测试下通过构造方法传递参数的情况


public class FramentTestActivity extends ActionBarActivity { 
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    if (savedInstanceState == null) { 
      getSupportFragmentManager().beginTransaction() 
          .add(R.id.container, new TestFragment("param")).commit(); 
    } 
  } 
  public static class TestFragment extends Fragment { 
    private String mArg = "non-param"; 
    public TestFragment() { 
      Log.i("INFO", "TestFragment non-parameter constructor"); 
    } 
    public TestFragment(String arg){ 
      mArg = arg; 
      Log.i("INFO", "TestFragment construct with parameter"); 
    } 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
        Bundle savedInstanceState) { 
      View rootView = inflater.inflate(R.layout.fragment_main, container, 
          false); 
      TextView tv = (TextView) rootView.findViewById(R.id.tv); 
      tv.setText(mArg); 
      return rootView; 
    } 
  } 
} 

可以看到我们传递过来的数据正确的显示了,现在来考虑一个问题,如果设备配置参数发生变化,这里以横竖屏切换来说明问题,显示如下

发生了什么问题呢?我们传递的参数哪去了?为什么会显示默认值?不急着讨论这个问题,接下来我们来看看Fragment.setArguments(Bundle bundle)这种方式的运行情况


public class FramentTest2Activity extends ActionBarActivity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
       super.onCreate(savedInstanceState); 
       setContentView(R.layout. activity_main); 
       if (savedInstanceState == null) { 
          getSupportFragmentManager().beginTransaction() 
                 .add(R.id. container, TestFragment.newInstance("param")).commit(); 
       } 
    } 
    public static class TestFragment extends Fragment { 
       private static final String ARG = "arg"; 
       public TestFragment() { 
          Log. i("INFO", "TestFragment non-parameter constructor" ); 
       } 
       public static Fragment newInstance(String arg){ 
          TestFragment fragment = new TestFragment(); 
          Bundle bundle = new Bundle(); 
          bundle.putString( ARG, arg); 
          fragment.setArguments(bundle); 
           return fragment; 
       } 
       @Override 
       public View onCreateView(LayoutInflater inflater, ViewGroup container, 
              Bundle savedInstanceState) { 
          View rootView = inflater.inflate(R.layout. fragment_main, container, 
                 false); 
          TextView tv = (TextView) rootView.findViewById(R.id. tv); 
          tv.setText(getArguments().getString( ARG)); 
           return rootView; 
       } 
    } 
} 

我们再来看看横竖屏切换后的运行情况

看到了吧,我们传递的参数在横竖屏切换的情况下完好保存了下来,正确的显示给用户
那么这到底是怎么回事呢,我们知道设备横竖屏切换的话,当前展示给用户的Activity默认情况下会重新创建并展现给用户,那依附于Activity的Fragment会进行如何处理呢,我们可以通过源码来查看

先来看看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 ; 
} 

由于我们的Fragment是由FragmentManager来管理,所以可以跟进FragmentManager.restoreAllState()方法,通过对当前活动的Fragmnet找到下面的代码块


 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); 
      } 
} 

接下来我们可以看看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 ; 
  } 

可以看到最终转入到Fragment.instantitate()方法


public static Fragment instantiate(Context context, String fname, Bundle args) { 
  try { 
    Class<?> clazz = sClaSSMap .get(fname); 
    if (clazz == null) { 
      // Class not found in the cache, see if it's real, and try to add it 
      clazz = context.getClassLoader().loadClass(fname); 
      sClassMap .put(fname, clazz); 
    } 
    Fragment f = (Fragment)clazz.newInstance(); 
    if (args != null) { 
      args.setClassLoader(f.getClass().getClassLoader()); 
      f. mArguments = args; 
    } 
    return f; 
  } catch (ClassNotFoundException e) { 
    throw new InstantiationException( "Unable to instantiate fragment " + fname 
        + ": make sure class name exists, is public, and has an" 
        + " empty constructor that is public" , e); 
  } catch (java.lang.InstantiationException e) { 
    throw new InstantiationException( "Unable to instantiate fragment " + fname 
        + ": make sure class name exists, is public, and has an" 
        + " empty constructor that is public" , e); 
  } catch (IllegalAccessException e) { 
    throw new InstantiationException( "Unable to instantiate fragment " + fname 
        + ": make sure class name exists, is public, and has an" 
        + " empty constructor that is public" , e); 
  } 

通过此方法可以看到,最终会通过反射无参构造实例化一个新的Fragment,并且给mArgments初始化为原先的值,而原来的Fragment实例的数据都丢失了,并重新进行了初始化

通过上面的分析,我们可以知道Activity重新创建时,会重新构建它所管理的Fragment,原先的Fragment的字段值将会全部丢失,但是通过

Fragment.setArguments(Bundle bundle)
方法设置的bundle会保留下来。所以尽量使用
Fragment.setArguments(Bundle bundle)
方式来传递参数

以上所述是小编给大家介绍的Android 中为什么要用Fragment.setArguments(Bundle bundle)来传递参数,希望对大家有所帮助,如果大家有任何疑问欢迎给我给我留言,小编会及时回复大家的!

您可能感兴趣的文章:Android intent之间复杂参数传递方法详解Android Activity之间相互调用与传递参数的原理与用法分析Android Activity中使用Intent实现页面跳转与参数传递的方法


--结束END--

本文标题: Android 中为什么要用Fragment.setArguments(Bundle bundle)来传递参数

本文链接: https://lsjlt.com/news/22659.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Android 中为什么要用Fragment.setArguments(Bundle bundle)来传递参数
    Fragment在Android3.0开始提供,并且在兼容包中也提供了Fragment特性的支持。Fragment的推出让我们编写和管理用户界面更快捷更方便了。 但当我们实例化...
    99+
    2022-06-06
    参数 bundle fragment Android
  • Android面试专题系列(六):Activity中为什么要用bundle来传递数据,而不用HashMap来代替?
    不诗意的女程序媛不是好厨师~ 转载请注明出处,From李诗雨—https://blog.csdn.net/cjm2484836553/article/details/105152708 面试官:“你一定看过Activity的onC...
    99+
    2022-06-06
    数据 activity hashmap bundle Android
  • Navigation Bundle怎么实现两个Fragment参数传递
    今天小编给大家分享一下Navigation Bundle怎么实现两个Fragment参数传递的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下...
    99+
    2023-07-05
  • Android 不同Activity间数据的传递 Bundle对象的应用
    在应用中,可能会在当跳转到另外一个Activity的时候需要传递数据过去,这时就可能用Bundle对象; 在MainActivity中,有一个导航至BActivity的Inte...
    99+
    2022-06-06
    数据 activity bundle Android
  • 在Android中通过Intent使用Bundle传递对象的使用方法
    Android开发中有时需要在应用中或进程间传递对象,下面详细介绍Intent使用Bundle传递对象的方法。 被传递的对象需要先实现序列化,而序列化对象有两种方式:java...
    99+
    2022-06-06
    方法 对象 intent bundle Android
  • Oracle中数据绑定和参数传递要注意什么
    在Oracle中,数据绑定和参数传递是非常重要的操作,要注意以下几点: 数据绑定是在SQL语句中使用变量来替代固定的数值或字符串...
    99+
    2024-04-09
    Oracle
  • Android 中怎么实现Activity 间传递参数
    这篇文章将为大家详细讲解有关Android 中怎么实现Activity 间传递参数,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1.传递简单数据在A Activity中findViewByI...
    99+
    2023-05-30
    android activity
  • mybatis3中@SelectProvider传递参数方式是什么
    这篇文章主要讲解了“mybatis3中@SelectProvider传递参数方式是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“mybatis3中@SelectProvider...
    99+
    2023-06-20
  • Vue中mapMutations传递参数方式是什么
    本篇内容主要讲解“Vue中mapMutations传递参数方式是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue中mapMutations传递参数方式是什么”吧!通过子组件定义的方法传递...
    99+
    2023-06-30
  • vue.js中怎么利用props传递参数
    vue.js中怎么利用props传递参数,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1. 问题发现在父组件中,需要向表格组件传递的数据有...
    99+
    2024-04-02
  • C++参数传递应用方式是什么
    本篇内容主要讲解“C++参数传递应用方式是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++参数传递应用方式是什么”吧!引用是C++中的概念,初学者容易把引用和指针混淆一起。 一下程序中,...
    99+
    2023-06-17
  • Python函数值传递、引用传递、形式参数和实际参数的区别是什么
    本篇内容主要讲解“Python函数值传递、引用传递、形式参数和实际参数的区别是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python函数值传递、引用传递、形式参数和实际参数的区别是什么”...
    99+
    2023-06-30
  • Python函数中*args和**kwargs来传递变长参数的用法
    单星号形式(*args)用来传递非命名键可变参数列表。双星号形式(**kwargs)用来传递键值可变参数列表。 下面的例子,传递了一个固定位置参数和两个变长参数。 def test_var_args(f...
    99+
    2022-06-04
    函数 变长 参数
  • C#中怎么将匿名方法作为参数传递
    C#中怎么将匿名方法作为参数传递,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。C#匿名方法作为参数传递C#匿名方法作为参数传递就和命名方法一样,C#匿名方法作为参数传递给函数是...
    99+
    2023-06-17
  • 使用python怎么在函数中传递实参
    这期内容当中小编将会给大家带来有关使用python怎么在函数中传递实参,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。python是什么意思Python是一种跨平台的、具有解释性、编译性、互动性和面向对象的...
    99+
    2023-06-14
  • jquery中怎么使用ajax向后台传递数组参数
    这篇文章给大家介绍jquery中怎么使用ajax向后台传递数组参数,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。需求: 在JS中向后台传递数组参数 分析: JS中的数组是弱类型的可以放...
    99+
    2024-04-02
  • Android中怎么使用Activity和Fragment传递数据
    Android中怎么使用Activity和Fragment传递数据,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。第一种方式,也是最常用的方式,就是使用Bundle来传递参数&n...
    99+
    2023-05-30
    fragment activity android
  • java中怎么用注解实现变量参数传递
    在Java中,可以使用注解来实现变量参数传递的方式是通过自定义注解和反射机制来实现。下面是一个示例代码: 首先定义一个自定义注解,...
    99+
    2024-03-12
    java
  • SpringBoot怎么用实体接收Get请求传递过来的多个参数
    这篇文章主要介绍了SpringBoot怎么用实体接收Get请求传递过来的多个参数的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇SpringBoot怎么用实体接收Get请求传递过来的多个参数文章都会有所收获,下面...
    99+
    2023-06-30
  • Android Activity中使用Intent实现页面跳转与参数传递的方法
    本文实例讲述了Android Activity中使用Intent实现页面跳转与参数传递的方法。分享给大家供大家参考,具体如下: 新建一个FirstAvtivity.java ...
    99+
    2022-06-06
    页面跳转 方法 参数 intent activity Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作