成员变量与片段中的setArguments

oob*_*yly 65 java android coding-style android-fragments

我注意到在片段的Android参考(特别是DialogFragment)中,他们做了一些与我期望的不同的事情:

1).使用public static foo newInstance()方法而不是构造函数.
2).使用setArguments而不是成员变量将值传递给onCreateDialog.

我已经读过,使用反射时newInstance似乎更适合.但是我真的不明白为什么他们通过捆绑传递参数.虽然使用成员变量会更安全(不使用字符串从地图中获取)并且会减少开销.

有什么想法吗?

Phi*_*art 48

我也偶然发现了这一点,并发现在Bundle实例字段上使用参数有一些优点:

  • 如果它在BundleAndroid系统中知道它并且可以创建和销毁你的Fragment(使用强制的无参数/默认构造函数和通常的生命周期方法),并再次传入参数包.这样,在低内存消除狂欢或最终的方向改变时,没有任何参数丢失(这在经过较少旋转的仿真器中开发之后首次部署到真实设备时经常会遇到这种情况).

  • 您可以BundleActivity原样的附加内容传递给Fragment布局中的嵌入内容; 例如,当我有一个Activity显示Fragment"全屏"并需要一些ID(或ContentProviderURI)来知道要显示/做什么时,我经常使用它.Bundle在我传递之前,我有时甚至会向(或副本)添加更多内容,例如

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
    
      if (savedInstanceState == null) { // not a re-creation
        final Bundle args = new Bundle(getIntent().getExtras());
        args.putInt(CoverImageFragment.BACKGROUND_RESOURCE, android.R.color.black);
        final Fragment fragment = CoverImageFragment.newInstance(args);
        getSupportFragmentManager()
          .beginTransaction()
          .add(android.R.id.content, fragment)
          .commit();
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 它保持了Fragment接近a的方式Activity,即Bundle"输入参数,无异常".

至于你提到的缺点:

  • 我觉得开销是最小的,因为你很可能不会被查询Bundle在紧密循环,所以在得到你的论点的数据出来后onCreate(), onViewCreate()等是没有那么糟糕.

  • 对于类型安全,Bundle有所有不同的getXXXX()方法,甚至重载,如果缺少/可选的话,提供默认值:)

至于newInstance()方法,我认为它们是封装newsetArguments()调用我的简单方法Fragment; 我有时会提供额外的MyFragment newInstance(String singleIdOfWhatToDisplay)创建既BundleFragment一气呵成,并返回一个现成的去Fragment实例.

  • newInstance不是工厂方法(如工厂方法模式,如果这是你的意思 - 请参阅http://en.wikipedia.org/wiki/Factory_method_pattern); 它是静态的,因此不能被覆盖,也不是它返回的类型的通用.据我所知,除了个人偏好之外,使用构造函数没有任何优势.但是,我依稀记得Fragments需要一个默认的构造函数?也许这里的想法是不必定义2个ctors,一个接受bundle参数而另一个是空的.最佳的揣测. (2认同)

rmi*_*lle 19

我发现这是一个非常令人困惑的问题(许多乱丢Android风景之一).

setArguments() 是Android的一个解决方法是非常无益的需要为Fragments提供无参数构造函数.

我的困惑波澜起伏.首先,这些方法你自然覆盖在你的Fragment(例如onCreate,onCreateView)收到一个Bundle表示该参数savedInstanceState你的Fragment.该实例的状态显然有NOTHING任何与你通过存储的值setArguments(),并通过检索getArguments().两者都使用a Bundle,两者Bundles都可能在相同的重写方法中访问,两者都没有任何关系.

其次,目前尚不清楚Android如何使用setArguments().Android调用你的无参数构造函数来重建你Fragment的旋转,但显然ALSO将调用在构造setArguments()时最后调用的方法Fragment.

咦????

太棒了,但是真的.所有这些Bundles都是setArguments()疯狂的创造,以弥补无参数Fragment构造函数的需要.

简而言之,我正在使用静态newInstance方法来创建我的Fragment.

public MyFragment() {
    //satisfy Android
}

public static MyFragment newInstance(long record_id) {
    Log.d("MyFragment", "Putting " + record_id + " into newInstance");
    MyFragment f = new MyFragment();
    Bundle args = new Bundle();
    args.putLong("record_id", record_id);
    f.setArguments(args);
    return f;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    /**
     * Perform an immediate check of arguments,
     * which ARE NOT the same as the bundle used
     * for saved instance state.
     */
    Bundle args = getArguments();
    if(args != null) {
        record_id = args.getLong("record_id");
        Log.d("MyFragment", "found record_id of " + String.valueOf(record_id));
    }
    if(savedInstanceState != null) {
        //now do something with savedInstanceState
    }
}
Run Code Online (Sandbox Code Playgroud)


Way*_*neJ 9

我是Android编程的新手,但这是我目前对该问题的理解:

Fragments的构造函数不能包含任何参数.当您的活动暂停时,您的片段可以被释放.在恢复活动之前,系统会创建一个新版本的Fragment来调用构造函数.如果使用非默认构造函数,那么Android应该如何知道Fragments构造函数的参数的类型和值是什么?

我不相信捆绑被释放.捆绑包精确地保持在周围,以便在使用默认构造函数重新创建它之后可以将其传递回Fragment.

Philipp Reichart在他的帖子中实现了这一点(实际上已经超过了.)

  • 你确定你是Android新手吗?这是一个简洁,精心设计的答案. (2认同)