Java 片段中的成员变量与setArguments

Java 片段中的成员变量与setArguments,java,android,coding-style,android-fragments,Java,Android,Coding Style,Android Fragments,我注意到,在Android的片段参考(特别是)中,它们做了一些与我预期不同的事情: 1) 。使用公共静态foo newInstance()方法而不是构造函数。 2). 使用setArguments而不是成员变量将值传递给onCreateDialog 我已经读到newInstance在使用反射时似乎更受欢迎。但是我真的不明白他们为什么要通过bundle传递参数。我认为使用成员变量会更安全(不使用字符串从映射中获取),并且会有更少的开销 有什么想法吗?我也偶然发现了这一点,并发现在实例字段上使用参数

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

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

我已经读到newInstance在使用反射时似乎更受欢迎。但是我真的不明白他们为什么要通过bundle传递参数。我认为使用成员变量会更安全(不使用字符串从映射中获取),并且会有更少的开销


有什么想法吗?

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

  • 如果它在
    捆绑包中
    ,Android系统会知道它,并可以创建和销毁你的
    片段
    (使用强制的无参数/默认构造函数和通常的生命周期方法),然后再次传入参数捆绑包。这样一来,在低内存杀戮狂欢中或最终的方向改变中,就不会丢失任何参数(在较少旋转的仿真器中进行开发后,在第一次部署到真实设备时,我经常会遇到这种情况)

  • 您只需将
    活动
    的附加
    原样传递给嵌入布局中的
    片段
    ;e、 g.当我有一个
    活动
    显示一个
    片段
    “全屏”并且需要一些ID(或
    内容提供者
    URI)来知道要显示/做什么时,我经常使用这个选项。有时,我甚至会在传递之前向
    捆绑包
    (或副本)添加更多内容,例如

    @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();
      }
    }
    
  • 它使
    片段
    的开发方式接近
    活动
    ,即
    捆绑
    作为“输入参数,无例外”

至于你提到的缺点:

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

  • 为确保类型安全,
    Bundle
    具有所有不同的
    getXXXX()
    方法,甚至在缺少某个内容/可选内容时重载以提供默认值:)


至于
newInstance()
方法,我认为它们是封装
new
setArguments()
对我的
片段的调用的一种简单方法;有时,我会提供一个额外的
MyFragment新实例(String singleIdOfWhatToDisplay)
,它一次性创建
捆绑包和
片段,并返回一个准备就绪的
片段
实例。

只想给参数增加一个缺点,就是必须动态创建片段。如果从xml创建,As参数将无法很好地工作。我真的很讨厌这一点。

我发现这是一个非常令人困惑的问题(Android环境中的许多问题之一)

setArguments()
是Android的一个变通方法,Android需要为片段提供一个无参数的构造函数

我一片混乱。首先,您在
片段
中自然覆盖的方法(例如
onCreate
onCreateView
)会收到一个
参数,该参数表示
片段
savedInstanceState
。此实例状态显然与通过
setArguments()
存储和通过
getArguments()
检索的值无关。两者都使用一个
捆绑包
,两个
捆绑包
都可能在同一个重写方法中访问,两者都与对方无关

其次,Android如何使用
setArguments()
还不清楚。Android在rotate上调用无参数构造函数来重建
片段
,但显然也会调用上次构造
片段
时调用的
setArguments()
方法

令人惊讶,但这是真的。所有这些使用
setArguments()创建
bundle
的疯狂行为都是为了补偿对无参数
片段
构造函数的需要

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

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

我对Android编程相当陌生,但这是我目前对这个问题的理解:

片段的构造函数不能有任何参数。当活动暂停时,可以释放片段。在活动恢复之前,系统将创建一个新版本的片段,并调用构造函数。如果使用非默认构造函数,Android如何知道片段构造函数的参数的类型和值

我不相信那个包被释放了。捆绑包被精确地保留,以便在使用默认构造函数重新创建后可以将其传递回片段


Philipp Reichart在他的帖子中回避了这一点(实际上不止回避。)

您可以使用
getActivity().getIntent().getExtras()
从fragment访问活动参数,它工作得很好。我认为传递参数需要在代码中创建片段。如果在xml中定义片段,我不记得有没有传递参数的方法。有吗?我正在尝试在片段的零参数构造函数中使用setArguments(new Bundle()),以解决无法在xml实例化片段中使用get/setArguments的问题。newInstance方法实现了构造函数无法实现的功能,而newInstance方法实现了什么?我可以从构造函数调用
setArguments
。@Matthias我认为在这种情况下创建工厂方法是更好的方式