Android开发之dagger2简单理解

理解简述

Android开发技术层出不穷。站在别人肩膀上看风景,的确省了不少事。前一段时间为了锻炼下自己的能力,就从鸿洋大神微信公众号的推送里面,下了个完整的项目,想试着自己跟着写一下,也算是追随下主流的脚步吧,这里给下下载的链接点击打开链接,作品的简介:微阅是一款使用 MVP + Retrofit2 + Rxjava + dagger2 等框架开发的阅读软件。包括新闻、视频、煎蛋三个模块,项目的大部分功能已经完成。 另有 kotlin版本。然后lz就下了项目在电脑上先跑一遍,然后就懵逼了,之前也没接触过dagger2,然后就上网搜了一下:是用来降低各个类之间的耦合度的一个依赖注入框架。

先说下大致的理解吧。假设我们有个类,叫做A,

然后我们有个类叫做B,然后我们需要在A里面使用到B,那么我们之前的做法就是在A里面对B进行实例化,但是这样一来,A和B之间的耦合度自然而然的高了。但是,我们使用dagger2以后的操作是:

1.首先将B的构造方法加上注解@inject;2.在我们的A里面添加@inject B b;这样就完成了B的实例化,我们就可以在A里面随意的使用B的方法和参数了。

其次,如果B的构造方法中有参数的话,如果参数为其他的类的话,则我们需要对这个类进行inject注解,实现B对该类的依赖,当然,有很多情况下,我们构造方法中的参数是不能使用inject注解的,比如第三方库。这时候的操作就是通过添加module来实现对第三方库的依赖,当我们使用module的时候,必须新建的一个文件是component,这个文件的作用就是将module和我们的类A链接起来,这样我们在A里面使用B的时候,系统就会去查找B的构造方法中的参数的提供者,就会通过component然后查找到module,我们在module里面向外部提供了我们需要的这个参数。

有个简图可以看下

我们在module中定义提供我们需要的参数的方法,然后再component里面定义inject方法,链接我们需要使用到module提供参数的类。具体的dagger2 的语法,大家在百度一搜就可以搜到,这里只是通过比较通俗的理解,来理解dagger2的使用。

另外一点就是在看这个项目的时候,发现新建了两个module。一个是提供我们网络请求的module,还有一个是application的module,然后对应的是两个component,我们在httpComponent里面实现inject方法,然后将这个component依赖给applicationComponent,在applicationComponent中,提供的方法是包括我们在两个module中通过provide注解的方法,applicationComponent的使用的地方是application中,然后httpComponent的使用是在我们具体的类中。

项目中的实际应用

跟着具体的代码我们来具体理解下dagger2的使用。

1.@inject

具体的应用就是我们的activity和presenter,我们对presenter的构造方法进行注解

public class ArticleReadPresenter extends BasePresenter<ArticleReadContract.View> implements ArticleReadContract.Presenter {
    NewsApi mNewsApi;

    @Inject
    public ArticleReadPresenter(NewsApi newsApi) {
        this.mNewsApi = newsApi;
    }

然后在activity里面写下对应的inject,系统就会通过二者之间的对应关系,查找我们依赖类的实例

public abstract class BaseActivity<T1 extends BaseContract.BasePresenter> extends SupportActivity implements IBase, BaseContract.BaseView {
    protected View mRootView;
    protected Dialog mLoadingDialog = null;
    Unbinder unbinder;

    @Nullable
    @BindView(R.id.SimpleMultiStateView)
    SimpleMultiStateView mSimpleMultiStateView;

    @Nullable
    @Inject
    protected T1 mPresenter;

这样,我们在activity里面就可以使用presenter,而不用再去通过new来实例化。

2.@module

我们可以看到presenter中的构造方法是带参的,这里的api的设定就是进行我们的retrofit的一些初始化操作,前文也提到了第三方库是不能通过inject来注解的,所以这里我们新建了一个module文件来提供我们需要的这个api文件

@Module
public class HttpModule {

    @Provides
    OkHttpClient.Builder provideOkHttpClient() {
        // 指定缓存路径,缓存大小100Mb
        Cache cache = new Cache(new File(MyApp.getContext().getCacheDir(), "HttpCache"),
                1024 * 1024 * 100);
        return new OkHttpClient().newBuilder().cache(cache)
                .retryOnConnectionFailure(true)
                .addInterceptor(RetrofitConfig.sLoggingInterceptor)
                .addInterceptor(RetrofitConfig.sRewriteCacheControlInterceptor)
                .addNetworkInterceptor(RetrofitConfig.sRewriteCacheControlInterceptor)
                .connectTimeout(10, TimeUnit.SECONDS);
    }

//    @Provides
//    Retrofit.Builder provideBuilder(OkHttpClient okHttpClient) {
//        return new Retrofit.Builder()
//                .addConverterFactory(GsonConverterFactory.create())
//                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
//                .client(okHttpClient);
//    }

    @Provides
    NewsApi provideNetEaseApis(OkHttpClient.Builder builder) {
        builder.addInterceptor(RetrofitConfig.sQueryParameterInterceptor);

        Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(builder.build());

        return NewsApi.getInstance(retrofitBuilder
                .baseUrl(ApiConstants.sIFengApi)
                .build().create(NewsApiService.class));
    }

    @Provides

    JanDanApi provideJanDanApis(OkHttpClient.Builder builder) {

        Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(builder.build());

        return JanDanApi.getInstance(retrofitBuilder
                .baseUrl(ApiConstants.sJanDanApi)
                .build().create(JanDanApiService.class));
    }

我们可以看到首先是将我们新建的module文件通过@module给注解,告诉系统,这是个module文件,然后在里面写我们提供参数的方法,可以看到方法的命名是provide+参数,首先第一个参数是初始化OK HTTP client,因为在下面两个方法中,是需要使用到的。下面的两个方法就是提供我们需要的api方法,可以看到我们是进行了retrofit的初始化。

我们还新建了一个ApplicationModule文件:

@Module
public class ApplicationModule {

    private Context mContext;

    public ApplicationModule(Context context) {
        this.mContext = context;
    }

    @Provides
    MyApp provideApplication() {
        return (MyApp) mContext.getApplicationContext();
    }

    @Provides
    Context provideContext() {
        return mContext;
    }

提供了application和context。

3.component

component就是起到桥梁的作用。

先看HTTPComponent,

@Component(dependencies = ApplicationComponent.class)
public interface HttpComponent {

    void inject(VideoFragment videoFragment);

    void inject(DetailFragment detailFragment);

    void inject(JdDetailFragment jdDetailFragment);

    void inject(ImageBrowseActivity imageBrowseActivity);

    void inject( com.will.weiyue.ui.news.DetailFragment detailFragment);

    void inject(ArticleReadActivity articleReadActivity);

    void inject(NewsFragment newsFragment);

}

里面定义了很多的inject方法,里面的参数代表的是,谁需要使用到我们在module中定义的方法的类。同时还可以看到这个接口的注解是通过component然后是dependencies,通过这个方式,我们就实现了其他的component对本component的依赖。

再看ApplixationComponent.

@Component(modules = {ApplicationModule.class,HttpModule.class})
public interface ApplicationComponent {

    MyApp getApplication();

    NewsApi getNetEaseApi();

    JanDanApi getJanDanApi();

    Context getContext();

}

本component的中的方法都是我们在上面提供的module中通过provide注解的方法。

4.application Component使用的地方

applicationcomponent使用是在application中进行了applicationmodule以及HTTPmodule的初始化。

  mApplicationComponent = DaggerApplicationComponent.builder()
                .applicationModule(new ApplicationModule(this))
                .httpModule(new HttpModule())
                .build();

5.inject方法中的参数对应的类中的实现

 DaggerHttpComponent.builder()
                .applicationComponent(appComponent)
                .build()
                .inject(this);

在我们的activity方法中写上上面的代码,就实现了我们的activity和我们的module之间通过component之间的链接,就可以使用了。

本文也算写完了,简单来说,如果我们的被依赖类的构造方法是没有参数的话,或者参数是可以通过inject注解的类的话,那么我们只需要使用inject分别注解依赖类和在被依赖类中inject就行;如果被依赖的类的构造方法牵扯到不能使用inject的话,则需要使用module来提供我们的这个参数,然后通过component来实现这种链接关系。

具体的使用方法以及参考这篇博文Dagger2从入门到放弃再到恍然大悟,感觉看完自己参考着项目也算是简单的理解了dagger2的使用方法吧,关键是不能只看,跟着写写才能明白其中的奥妙。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值