我正在寻找一个关于如何注入片段和传递参数的解决方案。我没有找到任何适当的解决方案,因为注入片段意味着构造函数对状态不安全。
有没有办法做到这一点,没有调用newInstance模式?
谢谢,
最好。
因为Android管理片段的生命周期,所以你应该通过它的bundle分离将状态传递给Fragment的问题,并使用可注入的dep注入Fragment。通常,分离这些的最佳方法是提供static factory method,您可能会调用newInstance模式。
public class YourFragment extends Fragment {
// Fragments must have public no-arg constructors that Android can call.
// Ideally, do not override the default Fragment constructor, but if you do
// you should definitely not take constructor parameters.
@Inject FieldOne fieldOne;
@Inject FieldTwo fieldTwo;
public static YourFragment newInstance(String arg1, int arg2) {
YourFragment yourFragment = new YourFragment();
Bundle bundle = new Bundle();
bundle.putString("arg1", arg1);
bundle.putInt("arg2", arg2);
yourFragment.setArguments(bundle);
return yourFragment;
}
@Override public void onAttach(Context context) {
// Inject here, now that the Fragment has an Activity.
// This happens automatically if you subclass DaggerFragment.
AndroidSupportInjection.inject(this);
}
@Override public void onCreate(Bundle bundle) {
// Now you can unpack the arguments/state from the Bundle and use them.
String arg1 = bundle.getString("arg1");
String arg2 = bundle.getInt("arg2");
// ...
}
}
请注意,这是一种不同于您可能习惯的注入类型:不是通过注入它来获取Fragment实例,而是告诉Fragment在它附加到Activity后稍后注入它自己。这个例子使用dagger.android进行注入,使用子组件和members-injection methods来注入@Inject-annotated
字段和方法,即使Android在Dagger控件之外创建Fragment实例也是如此。
另请注意,Bundle是一个通用的键值存储;我使用过“arg1”和“arg2”而不是想出更多有创意的名字,但是你可以使用你想要的任何字符串键。请参阅Bundle及其超类BaseBundle,以查看Bundle在其get
和put
方法中支持的所有数据类型。这个Bundle对于保存Fragment数据也很有用;如果你的应用被电话打断而且Android会破坏你的活动以节省内存,你可以使用onSaveInstanceState
将表单字段数据放入Bundle中,然后在onCreate
中恢复该信息。
最后,请注意,您不需要创建像newInstance
这样的静态工厂方法;你也可以让你的消费者创建一个new YourFragment()
实例并自己传递一个特定的Bundle设计。但是,此时Bundle结构将成为API的一部分,您可能不需要它。通过创建静态工厂方法(或Factory对象或其他结构),您可以将Bundle设计作为Fragment的实现细节,并为消费者提供记录且保存良好的结构以创建新实例。