MVP架构笔记之-DI框架dagger2

         dagger2在mvp架构开发中主要起到了解耦的作用,我的上一篇文章MVP架构笔记之初探--mvp原理写的是一个最为基础的MVP架构,其实啊,这个架构是耦合的一个架构,我们的view层持有一个MvpPresenter()对象实例;我们的P层构造函数里面又新建了一个m层的对象实例,这样view依赖presenter,presenter又依赖model就是一个紧耦合的架构。

          现在在我们用dagger2对上面的mvp架构进行改进,在这之前先对dagger2进行了解,首先dagger2的官网

https://google.github.io/dagger/    以及dagger2的github开源地址 https://github.com/google/dagger,dagger2几个新属性的价绍:

@Inject  可以注解成员变量和构造函数,如上面的view层持有的p的对象变量和p的构造函数
@Module可用来注解无法由我们注解构造函数的第三方类、系统类、接口类,如retrofit,okhttp,gson等
@Provides注解修饰的方法,一般用于@Module注解类中的方法,负责提供具体类型的依赖
@Componet
负责修饰接口或抽象类,提供inject抽象方法等待相应的页面oncreate时实现注入,提供
modules=xxmodule.class链接module,实现@Inject  和@Module中间链接桥的作用

还有一个非必需但很重要的,

@scope :作用域,dagger2给我们提供了一种@Singleton单例,其他的类型需要我们自己定义,比如@ApplicationScope@ActivityScope,@FragmentScope等,定义方式可以如下:

@Scope
@Retention(RUNTIME)
public @interface ActivityScope {}

需要了解更多scope原理请参考文档:http://www.cnblogs.com/tiantianbyconan/p/5095426.html

接下来,先来看一下我们改造过后的项目代码,首先我们看构造函数完成注入的方式activity中:

public class MainActivity extends AppCompatActivity implements MvpContract.View {

    @Inject
    TestPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DaggerMainActivityComponent.create().inject(this);
        setContentView(R.layout.activity_main);
        presenter.toString();
}

    @Override
    public void showData(String data) {
        Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showload() {

    }
}
public class TestPresenter {
    String temp;

    @Inject
    public TestPresenter() {
        temp = "测试数据";
    }

    public String toString() {
        return temp;
    }
}
@Component
public interface MainActivityComponent {
    void inject(MainActivity activity);
}

为了测试方便,我新建了一个presenter,因为我在presenter中暂时还不想拿model和view对象,如上,我们发现activity的代码变得简单了许多,其中最关键的步骤就是我们开始注解的这一步

DaggerMainActivityComponent.create().inject(this);

这一步事真正实现presenter对象的实例化的,不然你可以把这行代码去掉,看你的presenter会不会报空指针异常,当然我们并没有写DaggerMainAcitivityComponent这类,这个类是我们的链接桥MainActivitiyComponent运行时生成的类,所以我们需要先把工程build一下才能调用这个类。注意:上述案例是在项目的mvpdagger2分支

接下来,我们来看一下当包含module时得实现方式,先看看我们得工程目录,我对代码进行了分包:

相比于前一个案例,确实复杂了不少,但分得却很明确,framework包下主要定义一些抽象得接口和公用得东西;di包下主要定义了module和component,前面我们也定义了component 的;mvp下对主要功能进行分层,契约类、M层、P层和v层,整个架构的思想如下图:

可以看到我们得契约类和先前得不太一样了,主要作用是对model和view层进行管理,即我们需要在presenter中处理的类对象,契约类如下:

public interface MainContract {
    //对于经常使用的关于UI的方法可以定义到IView中,如显示隐藏进度条,和显示文字消息
    interface View extends IView {
        void showData(String string);
    }

    //Model层定义接口,外部只需关心Model返回的数据,无需关心内部细节,即是否使用缓存
    interface Model extends IModel {
        String getData();
    }
}

接下来实现model层:

@ActivityScope
public class MainModel implements MainContract.Model {

    @Inject
    public MainModel() {
        //获取网络数据或者缓存数据
    }

    @Override
    public void onDestroy() {
    }

    @Override
    public String getData() {
        return "来自model层得数据";
    }
}

可以看到我们对构造函数进行了注解,这里要写的原因是和我们module里面的写法有关系,如下:

@Module
public class MainModule {
    private MainContract.View view;

    /**
     * 构建MainModule时,将View的实现类传进来,这样就可以提供View的实现类给presenter
     *
     * @param view
     */
    public MainModule(MainContract.View view) {
        this.view = view;
    }

    @ActivityScope
    @Provides
    MainContract.View provideMainView() {
        return this.view;
    }

    @ActivityScope
    @Provides
    MainContract.Model provideMainModel(MainModel model) {
        return model;
    }

//    @ActivityScope
//    @Provides
//    MainContract.Model provideMainModel() {
//        return new MainModel();
//    }
}

我们写的函数需要给函数提供值,所以注解了构造函数,当然如果换成下面不提供值,直接新建对象的话就不需要提供数据的来源了,自然也不需要@inject model 的构造函数;你可以跑一跑程序试试,两种是一样的效果。在如上两个类中我们都看到了有一个自定义注解@ActivityScope  ,表示只针对当前的Activity 有效,限制作用域范围,注解在类上表示类,注解在方法上表示方法,把modlue都写好了就该我们的连接器component登场了,如下:

@ActivityScope
@Component(modules = MainModule.class)
public interface MainComponent {
    void inject(MainActivity activity);
}

这里是一个接口,暴露了抽象方法给外部,由MainModule提供数据,等着页面来注解,同样在activity里面进行数据的注入操作,如下:

@Inject
    MainPresenter mainPresenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerMainComponent.builder()
                .mainModule(new MainModule(this))
                .build()
                .inject(this);

        mainPresenter.getData();
    }
@Override
    public void showData(String string) {
        Log.e("yy", string);
    }

至此,我们就完成了整个主流程的操作。还有一个默认的@scope操作符@Singleton我忘记介绍了,其实和@ActivityScope类似,可以修饰相应的类和方法,如下:

@Singleton
    @Provides
    MainContract.Model provideMainModel(MainModel model) {
        return model;
    }

表示单例model,最后运行一下我们的程序结果如下:


代码在项目的mvpdagger2module分支,通过这两个案例我们对dagger2的使用有了一个初步的了解,其实dagger2还有更强大的用法,dagger.android,这个我也还没掌握。哈哈,大家可以看下引入规则,dagger2:

implementation 'com.google.dagger:dagger:2.14.1'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.14.1'

dagger2.android 需要内外添加:

implementation 'com.google.dagger:dagger-android:2.14.1'
    implementation 'com.google.dagger:dagger-android-support:2.14.1'
    // if you use the support libraries
    annotationProcessor 'com.google.dagger:dagger-android-processor:2.14.1'

最后,给出代码的git地址:

https://github.com/yangyong915/MvpManager-yy

如果你觉得好,一定记得STAR哦。












  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值