出来混迟早要还的,技术债Dagger2:Android篇(下)进一步理解Dagger

编程入门 行业动态 更新时间:2024-10-09 08:29:11

出来混迟早要还的,<a href=https://www.elefans.com/category/jswz/34/1770192.html style=技术债Dagger2:Android篇(下)进一步理解Dagger"/>

出来混迟早要还的,技术债Dagger2:Android篇(下)进一步理解Dagger

前言

警告!这不是一个干货的文章!

个人认为,学技术不宜太浮躁。对于一项技术一味地追求干货其实并不一定有用,货太干容易噎着,哈哈~不如循序渐进慢下来,一点点去体会技术的前因后果。(这个系列适合于:了解但没有在项目里大规模应用Dagger2的读者)

出来混迟早要还的,技术债Dagger2:基础篇

出来混迟早要还的,技术债Dagger2:Android篇(上)

出来混迟早要还的,技术债Dagger2:Android篇(中)@Scope、@Singleton

本以为阅读一些文档,写一些Demo就能驾驭工作中的项目...我错了,我再也不会有这么愚蠢的想法了... 这么多依赖关系,谁扛得住啊!所以还是一点点来吧。

正文

前俩篇文章过后,我猜大家对下面的代码已经很熟悉了:

@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {void inject(MainActivity mainActivity);SharedPreferences getSharedPrefs();
}@Module
public class AppModule {Application application;public AppModule(Application application) {this.application = application;}@ProvidesApplication providesApplication() {return application;}@Provides@Singletonpublic SharedPreferences providePreferences() {return application.getSharedPreferences(DATA_STORE,Context.MODE_PRIVATE);}
}DaggerAppComponent appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)) .build();
复制代码

很基本,很简单的Dagger应用。不过大家有没有感觉到这个appModule(new AppModule(this))特别烦?安利我用的时候,说依赖注入,看不见new。我哼哧哼哧写这么多,这不还是new出来的?

那么问题来了,是不是可以不需要appModule(new AppModule(this))呢?当然可以。用过Dagger-Android的朋友,肯定很清楚,的确看不到任何new。那么这篇文章,咱们就来看看如何彻底不用new。

当然这也是Dagger-Android的原理

@Component.Builder

做这一切的前提是这个注解。这个注解是干啥的呢?说白了,给Component提供Module的依赖。

咱们先来想一个问题,下面代码存在的意义:

DaggerAppComponent appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)) .build();
复制代码

Dagger为我们所需的依赖生成实例,那么必然需要构建整个依赖关系网。Dagger就算是再神奇,也不可能凭空把整个我们所需要依赖关系构建出来,所以需要我们适时的“提供和引导”。那么new AppModule(this)就是给Dagger进行提供,因为从我们上述的代码中,Dagger是不知道该怎么去实例化这个AppModule,因此需要我们对其进行提供。

那么话又说回来,我们在上述的代码中,告诉它如何去实例化AppModule,不就可以避免我们手动去new AppModule(this)了么?

没错,@Component.Builder就是做这个的。

累死了,绕了一圈不知道大家理没理解@Component.Builder存在的含义了。

AppModule(Application application)

对于我们的AppModule来说,实例化它的关键是如何提供一个Application

public AppModule(Application application) {this.application = application;
}
复制代码

对于Dagger也是如此,它不能实例化AppModule的原因是它不知道或者说没办法去获取一个Application实例。因此,对于Dagger来说,我们应该给它提供Application的实例,而非AppModule

开始改造

改造需要一步步来:第一步,我们使用@Component.Builder去改造AppComponent

@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {void inject(MainActivity mainActivity);SharedPreferences getSharedPrefs();// 改造内容@Component.Builderinterface Builder {AppComponent build();// 此时还未改造这行代码Builder appModule(AppModule appModule);}
}
复制代码

现在我们告诉了Dagger,你要以@Component.Builder注解的接口那样去实例化我们所需的AppComponent

是不是发现这里添加的方法和DaggerAppComponent生成的代码很像?没错Dagger默认实例化AppComponent就是以这种代码进行的。

不过,对于我们这个AppModule来说,我们不需要关系它是怎么初始化(因为我们只需要它所提供给我们的依赖)。对于Dagger来说也是如此: Dagger想要为我们提供被@Provides标注的依赖,只需要拥有Application实例即可。因为只要拥有Application实例Dagger就有办法实例化AppModule,直接new即可。

所以这里我们需要一种方式来告诉Dagger:我要提供给你,在@Module中需要的内容。对于咱们的这个demo来说,咱们需要用一种方式把Dagger所需要的Application给他。

而做到这一点的就是@BindsInstance

@BindsInstance

按照官网的介绍,此注解用于标识Component Builder/SubComponent Builder中的某个方法,该方法允许将实例绑定到Component中。

所以对于我们的AppModule来说,它只需要提供@Provides的内容就可以了!,它所需要的,Dagger会按照我们的“指示”,注入进来。也就是这个样子:

@Module
public class AppModule {@Provides@Singleton// 外部传入Application实例(Dagger会按照我们的“指示”,注入进来)public SharedPreferences providePreferences(Application application) {return application.getSharedPreferences("store", Context.MODE_PRIVATE);}}
复制代码

而我们的AppConponent这样就可以了:

@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {void inject(MainActivity mainActivity);SharedPreferences getSharedPrefs();@Component.Builderinterface Builder {AppComponent build();@BindsInstance // 此时的application就会被,注入到AppModule的providePreferences方法中Builder application(Application application);      }
}
复制代码

build过后,我们初始化DaggerAppComponent,只需如此写:

DaggerAppComponent appComponent = DaggerAppComponent.builder().application(this).build();
复制代码

那么Dagger是如何为我们生成DaggerAppComponent的呢?

public final class DaggerAppComponent implements AppComponent {private Provider<Application> applicationProvider;private Provider<SharedPreferences> providePreferencesProvider;private DaggerAppComponent(Builder builder) {initialize(builder);}public static AppComponent.Builder builder() {return new Builder();}@SuppressWarnings("unchecked")private void initialize(final Builder builder) {this.applicationProvider = InstanceFactory.create(builder.application);this.providePreferencesProvider =DoubleCheck.provider(AppModule_ProvidePreferencesFactory.create(builder.appModule, applicationProvider));}@Overridepublic void inject(MainActivity mainActivity) {}@Overridepublic SharedPreferences getSharedPrefs() {return providePreferencesProvider.get();}private static final class Builder implements AppComponent.Builder {private AppModule appModule;private Application application;@Overridepublic AppComponent build() {if (appModule == null) {this.appModule = new AppModule();}if (application == null) {throw new IllegalStateException(Application.class.getCanonicalName() + " must be set");}return new DaggerAppComponent(this);}@Overridepublic Builder application(Application application) {this.application = Preconditions.checkNotNull(application);return this;}}
}
复制代码

对于AppModule来说,只是简单的new出来,当我们需要@Provides时,只是将所需的application传进去。而我们的application以成员变量的身份呆在了DaggerAppComponent“体内”。

尾声

这篇内容,其实并不是为了去讲@Component.Builder@BindsInstance。而是尽可能的通过它们,来加深大家去Component和Module的理解。去感受Dagger的实现,更好的去理解依赖注入。对与我们而言,需要用其形,学其神。

这样我们才不会受制于框架,而是驾驭框架。

我是一个应届生,最近和朋友们维护了一个公众号,内容是我们在从应届生过渡到开发这一路所踩过的坑,以及我们一步步学习的记录,如果感兴趣的朋友可以关注一下,一同加油~

转载于:

更多推荐

出来混迟早要还的,技术债Dagger2:Android篇(下)进一步理解Dagger

本文发布于:2024-02-13 09:09:17,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1757933.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:技术   Dagger   Android

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!