Héc*_*tor 6 android dependency-injection dagger-2
我在Dagger 2中有与范围相关的错误,我试图理解如何解决它.
我有一个CompaniesActivity显示公司.当用户选择项目时,将显示所选公司的员工EmployeesActivity.当用户选择员工时,她的详细信息显示在EmployeeDetailActivity.
class Company {
List<Employee> employees;
}
Run Code Online (Sandbox Code Playgroud)
类CompaniesViewModel包含公司和选定的公司(或null):
class CompaniesViewModel {
List<Company> companies;
Company selected;
}
Run Code Online (Sandbox Code Playgroud)
CompaniesActivity提到CompaniesViewModel:
class CompaniesActivity extends Activity {
@Inject
CompaniesViewModel viewModel;
@Override
protected void onCreate(Bundle b) {
//more stuff
getComponent().inject(this);
showCompanies(viewModel.companies);
}
//more stuff
private onCompanySelected(Company company) {
viewModel.selected = company;
startActivity(new Intent(this, EmployeesActivity.class));
}
}
Run Code Online (Sandbox Code Playgroud)
类EmployeesViewModel包含员工和选定的员工(或null):
class EmployeesViewModel {
List<Employee> employees;
Employee selected;
}
Run Code Online (Sandbox Code Playgroud)
EmployeesActivity提到EmployeesViewModel:
class EmployeesActivity extends Activity {
@Inject
EmployeesViewModel viewModel;
@Override
protected void onCreate(Bundle b) {
//more stuff
getComponent().inject(this);
showEmployees(viewModel.employees);
}
//more stuff
private onEmployeeSelected(Employee emp) {
viewModel.selected = emp;
startActivity(new Intent(this, EmployeeDetailActivity.class));
}
}
Run Code Online (Sandbox Code Playgroud)
最后,EmployeeDetailActivity我从视图模型中选择了Employee并显示她的详细信息:
class EmployeeDetailActivity extends Activity {
@Inject
EmployeesViewModel viewModel;
@Override
protected void onCreate(Bundle b) {
//more stuff
getComponent().inject(this);
showEmployeeDetail(viewModel.selected); // NullPointerException
}
}
Run Code Online (Sandbox Code Playgroud)
我得到NullPointerException因为EmployeesViewModel实例与EmployeesActivitythe不同EmployeeDetailActivity,在第二个中,viewModel.selected是null.
这是我的匕首模块:
@Module
class MainModule {
@Provides
@Singleton
public CompaniesViewModel providesCompaniesViewModel() {
CompaniesViewModel cvm = new CompaniesViewModel();
cvm.companies = getCompanies();
return cvm;
}
@Provides
public EmployeesViewModel providesEmployeesViewModel(CompaniesViewModel cvm) {
EmployeesViewModel evm = new EmployeesViewModel();
evm.employees = cvm.selected.employees;
return evm;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这CompaniesViewModel是singleton(@Singleton)但EmployeesViewModel不是,因为每次用户选择公司时都必须重新创建(员工列表将包含其他项).
每次用户选择公司时,我都可以set让公司的员工参与EmployeesViewModel,而不是创建新的实例.但我想CompaniesViewModel是不变的.
我怎么解决这个问题?任何建议将不胜感激.
不幸的是,我认为你在这种情况下滥用DI框架,你遇到的问题是"代码味道" - 这些问题暗示你做错了什么.
应该使用DI框架将关键依赖项(协作者对象)注入顶级组件,执行这些注入的逻辑应该完全独立于应用程序的业务逻辑.
从第一眼看,一切看起来都很好 - 你使用Dagger注入CompaniesViewModel和EmployeesViewModel进入Activity.如果这些是真正的"对象",这可能没问题(虽然我不会这样做).但是,在您的情况下,这些是"数据结构"(因此您希望它们是不可变的).
对象和数据结构之间的区别并非易事,但非常重要.这篇博文非常好地总结了它.
现在,如果您尝试使用DI框架注入数据结构,最终将框架转换为应用程序的"数据提供者",从而将部分业务功能委托给它.例如:它看起来EmployeesViewModel是独立的CompaniesViewModel,但它是一个"谎言" - @Provides方法中的代码将它们逻辑地联系在一起,从而"隐藏"依赖性.在这种情况下,良好的"经验法则"是,如果DI代码依赖于注入对象的实现细节(例如,调用方法,访问字段等) - 它通常表示关注点分离不充分.
两个具体建议:
| 归档时间: |
|
| 查看次数: |
1856 次 |
| 最近记录: |