android - Dagger 2 - 无法将成员注入原始类型
问题描述
我需要三级继承并用dagger2注入
1.MainActivity
--1.1 MainSubActivity
----1.1.1 MainSubActivityOne
----1.1.2 MainSubActivityTwo(与MainSubActivityOne结构相同)
主要活动
public abstract class MainActivity<T extends MainPresenter> extends BaseActivity implements MainView{
@Inject
protected T mPresenter;
}
主讲者
public abstract class MainPresenter<T extends MainView> extends BasePresenter<T> { ... }
主视图
public interface MainView extends BaseView{ ... }
-- 主子活动
public abstract class MainSubActivity extends MainActivity<MainSubPresenter> implements MainSubView { ... }
-- MainSubPresenter
public abstract class MainSubPresenter<T extends MainSubView> extends MainPresenter<T> { ... }
-- 主子视图
public interface MainSubView extends MainView { ... }
---- MainSubActivityOne(与 MainSubActivityTwo 相同):
public class MainSubActivityOne extends MainSubActivity implements MainSubViewOne{
@Override
protected void onCreatePresenter(){
mPresenter.setView(this);
mPresenter.onCreate();
}
@Override
protected void initializeDagger() {
getActivityComponent().inject(this);
}
}
---- MainSubPresenterOne(与 MainPresenterTwo 相同):
public class MainSubPresenterOne extends MainSubPresenter<MainSubViewOne> { ... }
---- MainSubViewOne(与 MainSubViewTwo 相同):
public interface MainSubViewOne extends MainSubView { ... }
活动组件
@PerActivity
@Component(dependencies = ApplicationComponent.class, modules =
{ActivityModule.class})
public interface ActivityComponent {
void inject(MainActivity mainActivity);
}
活动模块
@Provides
@PerActivity
MainPresenter provideMainPresenter() {
return new MainSubPresenterOne();
}
当我只有两个级别时,一切正常,但现在我收到此错误:
...components/ActivityComponent.java:90: error: [Dagger/MembersInjection] Cannot inject members into raw type com.example.main.MainActivity
void inject(MainActivity mainActivity);
^
com.example.main.MainActivity is injected at
...components.ActivityComponent.inject(com.example.main.MainActivity)
如果我将活动组件更改为:
void inject(MainSubActivityOne activity);
void inject(MainSubActivityTwo activity);
我得到了下一个错误:
.../components/ActivityComponent.java:92: error: [Dagger/MissingBinding] com.example.main.MainSubPresenterOne cannot be provided without an @Provides-annotated method.
void inject(MainSubActivityOne mainActivity);
^
com.example.main.MainSubPresenter is injected at
com.example.main.MainActivity.mPresenter
com.example.main.MainSubPresenterOne is injected at
...components.ActivityComponent.inject(com.example.main.MainSubActivityOne)
解决方案
This line is your problem:
void inject(MainActivity mainActivity);
MainActivity<T>
needs a generic type argument, but that's irrelevant. It's an abstract class. You're not injecting this common parent class. You're injecting the instances of its concrete children. Here's what you should do instead:
void inject(MainSubActivityOne activity);
void inject(MainSubActivityTwo activity);
[Dagger/MissingBinding] com.example.main.MainSubPresenterOne cannot be provided without an @Provides-annotated method.
This is all true. Your MainSubActivityOne
expects a MainSubPresenterOne
here:
@Inject
protected T mPresenter;
Yet you only created a binding for MainPresenter
:
@Provides
@PerActivity
MainPresenter provideMainPresenter() {
return new MainSubPresenterOne();
}
This means that Dagger knows only how to inject a MainPresenter
, it doesn't care that the MainPresenter
is actually a MainSubPresenterOne
.
Instead, what I would do is to scope the concrete presenters and let them have an @Inject
constructor:
@PerActivity
public class MainSubPresenterOne extends MainSubPresenter<MainSubViewOne> {
@Inject
public MainSubPresenterOne() {
// ...
}
// ...
}
Now Dagger knows how to inject MainSubPresenterOne
. Remove the @Provides
method.
I recommend the official documentation, which – among other things – explains that @Provides
is a kind of last resort and you should prefer @Inject
on the types under your control.
Alternatively you would
@Inject
protected MainPresenter mPresenter;
and create a separate subcomponent for each of your activities with a module providing the actual presenter:
@Module
abstract class MainSubActivityOneModule {
@Binds
abstract MainSubPresenter<MainSubViewOne> bindMainPresenter(MainSubPresenterOne impl);
}
This assumes that the activity doesn't care about the concrete implementation of its presenter, which may or may not be what you want.
推荐阅读
- xml - gnuradio OOT 模块 xml 文件有解析错误
- apache-camel - 在同一 Camelcontext 内的路由之间传递交换属性
- ajax - 数据表:用于显示每个文件名的照片的按钮
- javascript - 如何防止从我的角度站点直接访问 bootstrap.min.js?
- javascript - 如何根据文本区域中的字符数查找成本
- excel - vba - 根据定义的值更改单元格的颜色
- dialogflow-es - 如何在对话框流中创建带有日期的自定义实体
- symfony - symfony 4 json_login JWT 401 凭证错误
- python - SQLAlchemy Bakery -Function 需要一定的数组大小
- c++ - 在 C++ 中运行时更改操作