当前位置:  开发笔记 > 数据库 > 正文

了解Dagger 2中的范围

如何解决《了解Dagger2中的范围》经验,为你挑选了1个好方法。

我在Dagger 2中有与范围相关的错误,我试图理解如何解决它.

我有一个CompaniesActivity显示公司.当用户选择项目时,将显示所选公司的员工EmployeesActivity.当用户选择员工时,她的详细信息显示在EmployeeDetailActivity.

class Company {
    List employees;
}

CompaniesViewModel包含公司和选定的公司(或null):

class CompaniesViewModel {
    List companies;
    Company selected;
}

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));
    }

}

EmployeesViewModel包含员工和选定的员工(或null):

class EmployeesViewModel {
    List employees;
    Employee selected;
}

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));
        }

    }

最后,EmployeeDetailActivity我从视图模型中选择了Employee并显示她的详细信息:

  class EmployeeDetailActivity extends Activity {

        @Inject
        EmployeesViewModel viewModel;

        @Override
        protected void onCreate(Bundle b) {
            //more stuff
            getComponent().inject(this);
            showEmployeeDetail(viewModel.selected); // NullPointerException
        }
    }

我得到NullPointerException因为EmployeesViewModel实例与EmployeesActivitythe不同EmployeeDetailActivity,在第二个中,viewModel.selectednull.

这是我的匕首模块:

@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;
    }

}

请注意,这CompaniesViewModel是singleton(@Singleton)但EmployeesViewModel不是,因为每次用户选择公司时都必须重新创建(员工列表将包含其他项).

每次用户选择公司时,我都可以set让公司的员工参与EmployeesViewModel,而不是创建新的实例.但我想CompaniesViewModel是不变的.

我怎么解决这个问题?任何建议将不胜感激.



1> Vasiliy..:

不幸的是,我认为你在这种情况下滥用DI框架,你遇到的问题是"代码味道" - 这些问题暗示你做错了什么.

应该使用DI框架将关键依赖项(协作者对象)注入顶级组件,执行这些注入的逻辑应该完全独立于应用程序的业务逻辑.

从第一眼看,一切看起来都很好 - 你使用Dagger注入CompaniesViewModelEmployeesViewModel进入Activity.如果这些是真正的"对象",这可能没问题(虽然我不会这样做).但是,在您的情况下,这些是"数据结构"(因此您希望它们是不可变的).

对象和数据结构之间的区别并非易事,但非常重要.这篇博文非常好地总结了它.

现在,如果您尝试使用DI框架注入数据结构,最终将框架转换为应用程序的"数据提供者",从而将部分业务功能委托给它.例如:它看起来EmployeesViewModel是独立的CompaniesViewModel,但它是一个"谎言" - @Provides方法中的代码将它们逻辑地联系在一起,从而"隐藏"依赖性.在这种情况下,良好的"经验法则"是,如果DI代码依赖于注入对象的实现细节(例如,调用方法,访问字段等) - 它通常表示关注点分离不充分.

两个具体建议:

    不要将业务逻辑与DI逻辑混合在一起.在您的情况下 - 不要注入数据结构,而是注入提供对数据的访问(坏)的对象,或者在抽象数据时更好地公开所需的功能(更好).

    我认为您在多个屏幕之间共享视图模型的尝试并不是一个非常强大的设计.最好为每个屏幕设置一个单独的View-Model实例.如果你需要在屏幕之间"共享"状态,那么,根据具体要求,你可以用1)Intent extras 2)全局对象3)共享首选4)SQLite

推荐阅读
黄晓敏3023
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有