成员变量与片段中的 set 参数

我注意到,在Android对Fragments(特别是DialogFragment)的引用中,他们做了一些与我期望的不同的事情:

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

我读过,在使用反射时,newInstance似乎是可取的。但是我真的不明白为什么他们通过捆绑包传递参数。不过,使用成员变量会更安全(不使用字符串从映射中获取),并且开销会更少。

有什么想法吗?


答案 1

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

  • 如果它在Android系统中,知道它并且可以创建和销毁您的(使用强制性的无参数/默认构造函数和通常的生命周期方法),然后再次传入参数包。这样,在低内存杀戮狂欢或最终的方向变化中就不会丢失任何争论(这通常会在旋转较少的模拟器中开发后首次部署到真实设备上时击中我)。BundleFragment

  • 您可以按原样将附加功能传递给嵌入在布局中的附加内容;例如,当我有一个显示“全屏”并且需要一些ID(或URI)来知道要显示/做什么时,我经常使用它。有时我甚至会在传递之前向(或副本)添加更多内容,例如BundleActivityFragmentActivityFragmentContentProviderBundle

    @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();
      }
    }
    
  • 它保持开发的方式接近于,即 作为“输入参数,无例外”。FragmentActivityBundle

至于你提到的缺点:

  • 我认为开销是最小的,因为你很可能不会在紧密循环中查询,所以在 ,等中一次性获取你的参数数据并不是那么糟糕。BundleonCreate()onViewCreate()

  • 对于类型安全,具有所有不同的方法,甚至在缺少某些内容时提供默认值的重载/可选:)BundlegetXXXX()

至于方法,我认为它们是封装和调用我的一种简单方法;我有时会提供一个附加功能,可以一次性创建 和 并返回一个随时可用的实例。newInstance()newsetArguments()FragmentMyFragment newInstance(String singleIdOfWhatToDisplay)BundleFragmentFragment


答案 2

我发现这是一个非常令人困惑的问题(在Android领域散落的众多问题之一)。

setArguments()对于 Android 非常无用的需求,即为 Fragments 提供无参数构造函数,这是一种解决方法。

我的困惑一波接一波地袭来。首先,您在 (例如 , ) 中自然重写的方法会收到一个参数,该参数表示 .此实例状态显然与您通过 存储和检索的值没有任何关系。两者都使用 ,两者都可能在同一个被覆盖的方法中访问,两者彼此之间没有任何关系。FragmentonCreateonCreateViewBundlesavedInstanceStateFragmentsetArguments()getArguments()BundleBundles

其次,目前尚不清楚Android如何使用.Android调用您的无参数构造函数以在旋转时重建您的构造函数,但显然也会调用构造时上次调用的任何方法。setArguments()FragmentsetArguments()Fragment

哼????

令人惊叹,但确实如此。所有这些疯狂的创造都是为了弥补对无参数构造函数的需求。BundlessetArguments()Fragment

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

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