【发布时间】:2018-08-29 19:02:11
【问题描述】:
我正在寻找有关如何注入片段并向其传递参数的解决方案。 而且我没有找到任何合适的解决方案,因为通过构造函数注入片段意味着对状态不安全。
有没有办法做到这一点,而不调用 newInstance 模式?
谢谢,
最好的。
【问题讨论】:
我正在寻找有关如何注入片段并向其传递参数的解决方案。 而且我没有找到任何合适的解决方案,因为通过构造函数注入片段意味着对状态不安全。
有没有办法做到这一点,而不调用 newInstance 模式?
谢谢,
最好的。
【问题讨论】:
由于 Android 管理您的 Fragment 的生命周期,您应该将 通过其 bundle 将状态传递到 Fragment 和 使用可注入的 deps 注入 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 在附加后稍后注入自己到一个活动。此示例使用dagger.android 进行注入,它使用子组件和members-injection methods 注入@Inject-annotated 字段和方法,即使Android 在Dagger 控制之外创建Fragment 实例也是如此。
还要注意,Bundle 是一个通用的键值对存储;我使用了“arg1”和“arg2”,而不是想出更多有创意的名字,但你可以使用任何你想要的字符串键。请参阅 Bundle 及其超类 BaseBundle 以查看 Bundle 在其 get 和 put 方法中支持的所有数据类型。这个 Bundle 对于保存 Fragment 数据也很有用;如果您的应用被电话打断,Android 销毁您的 Activity 以节省内存,您可以使用 onSaveInstanceState 将表单字段数据放入 Bundle,然后在 onCreate 中恢复该信息。
最后请注意,您不需要创建像newInstance 这样的静态工厂方法;您还可以让您的消费者创建一个 new YourFragment() 实例并自己传递特定的 Bundle 设计。但是,此时 Bundle 结构成为您的 API 的一部分,这可能是您不想要的。通过创建静态工厂方法(或工厂对象或其他结构),您可以让 Bundle 设计成为您的 Fragment 的实现细节,并为消费者提供一个文档化且保存完好的结构以创建新实例。
【讨论】:
newInstance)可以接受任意数量的参数,Bundle 是一个键值存储(如 Map),您可以在其中插入任何类型的数据你想。我在这里只列出了一个参数(“arg”),但您可以输入任意数量的参数。有关它支持的所有 getter 和 setter,请参阅 the Bundle docs。
onAttach 中,如上所述。将状态和参数(“参数”)传递到 Fragment 的正确方法是使用 Bundle;您可以选择用静态工厂方法封装它。 (您也可以只要求您的消费者调用 new,然后使用特定的 Bundle 结构调用 setArguments。)