java Fragment 中的成员变量与 setArguments
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6677136/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Member variables vs setArguments in Fragments
提问by oobayly
I've noticed that in the Android reference for Fragments (notably DialogFragment) that they do a couple of things different from what I'd expect:
我注意到在 Fragments 的 Android 参考(特别是DialogFragment)中,他们做了一些与我期望的不同的事情:
1). Use public static foo newInstance()
method rather than a constructor.
2). Pass values to onCreateDialog using setArguments rather than member variables.
1)。使用public static foo newInstance()
方法而不是构造函数。
2)。使用 setArguments 而不是成员变量将值传递给 onCreateDialog。
I've read that newInstance appears to be preferrable when using reflection. However I really don't understand why they're passing parameters via a bundle. I'd have though using member variables would be safer (not using a string to fetch from a map) and would have less of an overhead.
我读过使用反射时 newInstance 似乎更可取。但是我真的不明白他们为什么要通过包传递参数。我认为使用成员变量会更安全(不使用字符串从地图中获取)并且开销更少。
Any thoughts?
有什么想法吗?
回答by Philipp Reichart
I've also stumbled upon this and found a few advantages to using the arguments Bundle
over instance fields:
我也偶然发现了这一点,并发现了Bundle
在实例字段上使用参数的一些优势:
If it's in a
Bundle
the Android system knows about it and can create and destroy yourFragment
(using the mandatory parameterless/default constructor and usual lifecycle methods), and just pass in the arguments bundle again. This way no arguments get lost on a low memory killing spree or the eventual orientation changes (this often hits me on first deploy to a real device after development in the less-rotating emulator).You can just pass the extras
Bundle
of anActivity
as-is to aFragment
embedded in the layout; e.g. I often use this when I have anActivity
that displays aFragment
"fullscreen" and needs some ID (orContentProvider
URI) to know what to display/do. I sometimes even add more stuff to aBundle
(or a copy) before I pass it on, e.g.@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(); } }
It keeps the way of developing a
Fragment
close to that of anActivity
, i.e.Bundle
as "input parameters, no exceptions".
如果它在
Bundle
Android 系统中知道它并且可以创建和销毁您的Fragment
(使用强制性的无参数/默认构造函数和通常的生命周期方法),并且只需再次传入参数包。这样一来,就不会因为内存不足而导致混乱或最终方向发生变化(这通常会让我在在旋转较少的模拟器中开发后第一次部署到真实设备时感到震惊)。您可以
Bundle
将Activity
原样的附加内容传递给Fragment
嵌入在布局中的内容;例如,当我有一个Activity
显示Fragment
“全屏”并且需要一些 ID(或ContentProvider
URI)来知道要显示/做什么时,我经常使用它。有时我什至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(); } }
它保持了
Fragment
接近于的开发方式Activity
,即Bundle
作为“输入参数,没有例外”。
As for the downsides you mentioned:
至于你提到的缺点:
I think the overhead is minimal because you most likely won't be querying the
Bundle
in a tight loop, so getting your argument data out once inonCreate()
,onViewCreate()
, etc. isn't that bad.For type-safety,
Bundle
has all the differentgetXXXX()
methods, and even overloads to provide a default value if a something is missing/optional :)
我觉得开销是最小的,因为你很可能不会被查询
Bundle
在紧密循环,因此让你的论点的数据进行一次onCreate()
,onViewCreate()
等是没有那么糟糕。对于类型安全,
Bundle
具有所有不同的getXXXX()
方法,甚至重载以在缺少某些内容/可选时提供默认值:)
As for the newInstance()
methods, I think of them as an easy way to encapsulate the new
and setArguments()
calls for my Fragment
; I sometimes provide an additional MyFragment newInstance(String singleIdOfWhatToDisplay)
that creates both the Bundle
and Fragment
in one go and returns a ready-to-go Fragment
instance.
至于newInstance()
方法,我认为它们是封装new
和setArguments()
调用 my的简单方法Fragment
;我有时会提供一个额外的MyFragment newInstance(String singleIdOfWhatToDisplay)
,一次性创建Bundle
和Fragment
并返回一个准备就绪的Fragment
实例。
回答by rmirabelle
I found this to be a HIGHLY confusing issue (one of many that litter the Android landscape).
我发现这是一个非常令人困惑的问题(Android 环境中的许多问题之一)。
setArguments()
is a workaround for Android's very unhelpful need to have a parameter-less constructor available for Fragments.
setArguments()
是 Android 需要为 Fragment 提供无参数构造函数的非常无益的解决方法。
My confusion came in waves. First, the methods you naturally override in your Fragment
(e.g. onCreate
, onCreateView
) receive a Bundle
parameter that represents the savedInstanceState
of your Fragment
. This instance state apparently has NOTHINGwhatsoever to do with the values you store via setArguments()
and retrieve via getArguments()
. Both use a Bundle
, both Bundles
are likely to be accessed within the same overridden method, neither have anything to do with each other.
我的困惑如潮水般涌来。首先,你在你的自然覆盖的方法Fragment
(例如onCreate
,onCreateView
)收到一个Bundle
表示该参数savedInstanceState
你的Fragment
。此实例状态显然与您通过 存储和检索的值没有任何关系。两者都使用 a ,两者都可能在同一个被覆盖的方法中访问,彼此之间没有任何关系。setArguments()
getArguments()
Bundle
Bundles
Second, it's unclear how Android uses setArguments()
. Android calls your parameter-less constructor to rebuild your Fragment
on rotate, but apparently ALSO will call whichever setArguments()
method was last called when the Fragment
was constructed.
其次,目前还不清楚 Android 如何使用setArguments()
. Android 调用您的无参数构造函数来重建您Fragment
的旋转,但显然也将调用构造setArguments()
时最后调用的任何方法Fragment
。
Huh????
咦???
Amazing, but true. All of this creating Bundles
with setArguments()
madness exists to compensate for the need of a parameter-less Fragment
constructor.
惊人,但真实。所有这些疯狂的创建Bundles
都是setArguments()
为了弥补对无参数Fragment
构造函数的需求。
In short, I'm using the static newInstance
method to create my 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
}
}
回答by WayneJ
I am pretty new to Android programming but this is my current understanding of the issue:
我对 Android 编程很陌生,但这是我目前对这个问题的理解:
The constructor for Fragments cannothave any parameters. When your activity is paused your Fragment can be released. Before your activity is resumed, the system creates a new version of your Fragment calling the constructor. If a non-default constructor is used, how is Android supposed to know what the types and values are for the arguments to your Fragments constructor?
Fragments 的构造函数不能有任何参数。当您的活动暂停时,您的 Fragment 可以被释放。在您的活动恢复之前,系统会调用构造函数创建一个新版本的 Fragment。如果使用非默认构造函数,Android 应该如何知道 Fragments 构造函数的参数的类型和值是什么?
I don't believe that bundle is released. The bundle is kept around precisely so that it can be passed back to your Fragment after it has been recreated with the default constructor.
我不相信该捆绑包已发布。该包被精确地保留,以便它可以在使用默认构造函数重新创建后传递回您的 Fragment。
Philipp Reichart eluded to this in his post (actually more than eluded.)
Philipp Reichart 在他的帖子中回避了这一点(实际上不仅仅是回避。)
回答by havexz
Just want to add one more drawback to arguments is that you have to dynamically create fragments. As arguments does not work very well if you creating from the xml. And I really hate that.
只是想为参数添加另一个缺点是您必须动态创建片段。如果您从 xml 创建参数,则参数不会很好地工作。我真的很讨厌那样。