这是一个典型问题,因为对Dagger 2的对象初始化存在很多误解.
如果您的问题被标记为重复,请仔细阅读本文,并确保了解构造函数注入和现场注入之间的区别.
我尝试向Context我的演示者注入一个,但在尝试使用它时我得到一个NullPointerException.
class MyPresenter {
@Inject Context context;
private MyView view;
@Inject
MyPresenter(MyView view) {
this.view = view;
}
}
Run Code Online (Sandbox Code Playgroud)
我的模块看起来像这样
@Module
class MyModule {
@Provides
MyPresenter provideMyPresenter(MyView view) {
return new MyPresenter(view);
}
}
Run Code Online (Sandbox Code Playgroud)
我在这里的活动中注入了演示者:
class MyActivity extends Activity {
@Inject MyPresenter presenter;
@Override
public void onCreate(Bundle savedInstanceState) {
createMyActivityComponent().inject(this);
}
}
Run Code Online (Sandbox Code Playgroud)
以上包括构造函数和字段注入,但都没有做对.如果我们删除了所有@Inject注释,那么该示例的行为将相同,MyPresenter因为我们没有使用任何注释.
@Provides
MyPresenter provideMyPresenter(MyView view) {
// no constructor injection, we create the object ourselves!
return new MyPresenter(view);
}
// also no mention anywhere of component.inject(presenter)
// so the fields won't be injected either
Run Code Online (Sandbox Code Playgroud)
确保使用两种构造器注入或字段注入.混合两者通常表示您的设置或理解错误.
@Inject在场上是场注入的标记@Inject在构造函数上是构造函数注入的标记这意味着你的类应该有任何的
@Inject的构造,或@Inject上的所有字段进行初始化,但没有在构造!不要@Inject到处洒,希望事情有效!确保将注释放在需要的位置.不要混合场和构造函数注入!
构造函数注入应该优于字段注入,因为它创建了一个初始化和可用的对象.字段注入将与框架组件一起使用,其中框架创建对象.您必须手动调用component.inject(object)要执行的字段注入,或者当您尝试使用它们时,任何带注释的字段将为null.
顾名思义,您将依赖项作为参数放在构造函数中.构造函数上的注释告诉Dagger有关该对象的信息,然后它可以通过调用所有必需的依赖项来为您创建对象.Dagger也会在创建对象后注入任何带注释的字段或方法,但普通构造函数注入通常应该受到青睐,因为它不会隐藏任何依赖项.
创建对象的Dagger也意味着模块中不需要@Provides创建对象的方法.您需要做的就是添加@Inject到构造函数并声明依赖项.
class MyPresenter {
private Context context;
private MyView view;
@Inject
MyPresenter(MyView view, Context context) {
this.view = view;
this.context = context
}
}
Run Code Online (Sandbox Code Playgroud)
如果要将实现绑定到接口,则仍然无需自己创建对象.
@Module class MyModule {
@Provides
MyPresenter providePresenter(MyPresenterImpl presenter) {
// Dagger creates the object, we return it as a binding for the interface!
return presenter;
}
}
Run Code Online (Sandbox Code Playgroud)
甚至还有一个更短(更高性能)的上述用例版本:
@Module interface MyModule {
@Binds
MyPresenter providePresenter(MyPresenterImpl presenter)
}
Run Code Online (Sandbox Code Playgroud)
构造函数注入应该是使用Dagger的默认方式.确保你没有给new自己打电话或者你误解了这个概念.
有些时候你不能使用构造函数注入,例如,Android中的Activity由Framework创建,你不应该覆盖构造函数.在这种情况下,我们可以使用现场注入.
要使用字段注入,请注释要初始化的所有字段,并向应处理注入的组件@Inject添加void inject(MyActivity activity)方法.
@Component
interface MyComponent {
void inject(MyActivity activity);
}
Run Code Online (Sandbox Code Playgroud)
在代码中的某个地方,您必须调用component.inject(myActivity) 或者字段不会被初始化.例如inonCreate(..)
void onCreate(..) {
// fields still null / uninitialized
myComponent.inject(this);
// fields are now injected!
// ...
}
Run Code Online (Sandbox Code Playgroud)
现场注入不是传递性的.仅仅因为你注入了一个Activity,这并不意味着Dagger也会注入它注入的主持人的字段.您必须手动注入每个对象,这是您应该支持构造函数注入的一个原因.
有些工具可以帮助减轻创建组件和注入对象的样板,AndroidInjection.inject()这样就可以为您完成此任务,但仍有必要完成.另一个例子是AppInjector添加各种生命周期监听器来注入你的活动和片段,但它仍然会调用AndroidInjection然后创建你的组件并注入对象.
确保在使用之前注入对象,并且没有注释构造函数@Inject以避免混淆.
还有较少使用的方法注入,当然Dagger不能注入第三方库,您必须在模块中构建和提供这些库.
| 归档时间: |
|
| 查看次数: |
1218 次 |
| 最近记录: |