点赞注重,不再走失,你的支撑对我含义严峻!

Hi,我是丑丑。本文 「Android 路程」| 导读 —— 从零到无穷大 已录入,这里有 Android 进阶生长路程笔记 & 博客,欢迎跟着彭丑丑一同生长。(联络办法在 GitHub)


前语

  • 依托注入是项笔记本目组件解耦中非常重要的一个手法,Dagger2 和 Hilt 是在 Android 中最首要的依托注入结构;
  • 在这篇文章里,我将总结 Dagger2 的运用办法,假定能帮上忙,请有必要点赞加注重,这真的对我非常重要。

目录

Android | 从 Dagger2 到 Hilt 玩转依靠注入(一)


前置知识

这篇文章的内容会触及以下okhttp是干什么用的前置 / 相关知识,交心的我都帮你准备好了,请享受~

  • APT 【点赞催更】
  • Java | 注解(含 Kotlin)

1. 为什么要进行依托注入

依托注入(Dependency Injection,简称 DI)其实并不是一个很奥妙的概念,往往在不经意地间咱们就运用了依托注入。依托注okhttp封装入运用了 “控制反转(IoC)” 的原理,简略来说就是在类的外部结构依托项,运用结构器或许 setter 注入。

提示: 你往往在不经意间运用了依托注入的思想。

Android | 从 Dagger2 到 Hilt 玩转依靠注入(一)

运用依托注入可认为咱们带来什么长处呢?

  • 重用组件: 由于咱们在类外部结构依托项;
  • 组件appear解耦: 当咱们需求批改某个组件的完毕时,不需求在项目中进行许多改动;
  • 易检验: 咱们能够向依托方注入依托项的模仿完毕,这使得依工商银行托方的检验愈加简单;
  • 生命周期透明: 依托Go方不感知依托项创立 / 销毁的生命周期,这些能够交给依托注入结构处理。

2. Android 依托注入结构

当只需一个依托项时,手动进行依托注入很简略,但随着项目规划变大,手动注入会变得越来越杂乱。而运用依托注入结构javahdxx,能够让依托注入的过程愈加简洁,其他,依托注入结构往往还供给了处理依托项的生命周期的功用。从完毕上,依托注入结okhttp运用过程构能够归为两类:

  • 1、根据反射的动态计划: Guice、Dagger;
  • 2、根据编译时注解的静态计划(功能更高): Daggeokhttp是干什么用的r2、Happroveilt、ButterKnife。

提示:依托注入结构本javascript质上不是供给了依托注入的才华,而是选用了注解等办法让依托注入变得愈加简易。

在这里边,Dagger2 和 Hilt 是咱们今天谈论的主题。

  • Dagger2OKHttp Dagger 的姓名取自有向无环图(DAG,Directed acyclic graph),初步由 Square 安排开发,而后来的 Dagger2 和 Hilt 结构则由 Square 和 Googokhttp源码解析le 共同开发保护。

  • Hilt: Hilt 是 Dagger2 的二次封装,Hilt 本质上是对 Dagger 进行场景化。它为 Android 渠道制定了一系列规矩,大大简化了 Dagger2 的运用。在 Dagger2 里,你需求手动获取依托笔记本电脑性价比排行2020图和实施注入操作,而在 Hilt 里,注入会主动完毕,由于 Hilt 会自approve动找到 Andr笔记本cpu天梯图oid 体系组件中那些最佳的注入方位。

下面,咱们分别来谈论 Dagger2 和 Hilt 两个结构。原本我不计划介绍太多 Dagger2 的内容(由于在 Android 里咱们是直接运用 Hilt),考虑到两者的联络仍是觉得仍是有必要把 Dagger2 讲清楚,才华真实了解 Hilt 帮咱们做了什么。


3. Dagger2 运用教程

提示: 我在学习 Dagger2 时,也阅读了许多文章和官方文笔记档。有些作者会列举出一切注解的用法,有些作者只介绍用法而忽略说明主动生成的代码龚俊。我也在寻求一种易于了解 / 承受的讲法,最后我觉得先「基础注解」再「杂乱注解」,边介绍用法边说明主动生成代码的办法,或许是更简单了解的办法。等候得到你的反馈~

在谈论的过程中,咱们通过一个简略的比如来翻笔记本电脑排名前十开:假定咱们有一java怎样读个用户数据模块,它依托于两个依托项:

public class UserRepository {
private final UserLocalDataSource userLocalDatjava编译器aSource;
private final UsAPPerRemoteDataSource userRemoteDataSource;
public UserRepository(UserLocalDataSour笔记本ce userLocalDataSource, UserRemoteDataSource userRemoteDappearataSource) {
this.userLocalDataSource = userLocalDat笔记本电脑什么牌子好aSource;
this.userRemoteDataSource = userRemoteDataSource;
}application
}

Android | 从 Dagger2 到 Hilt 玩转依靠注入(一)

首要,你能够挑选不运用依托注入,那么你或许就会在项目多处重复构建,公积金缺点咱们在第一节都谈论过了。

new UserRepository(new UserLocalDataSource(), new UserRemoveDataSource());

后来,有寻求的你现已初步运用依托注入,你写了一个全google局的东西办法:

public static UserRepositGoory get() {
return new UserRepository(new UserLocalDataSource(), new UserRemoveDataSource()approach);
}

这确实能满足需求,然而在真实宫外孕项目中,模块之间的依托联络java游戏往往比这个比如google要杂乱得多。此刻,假定笔记本电脑什么牌子好经常手动编写依托注入的模板代码,不仅耗时耗力,也简单犯错。okhttp3源码剖析下面,咱们初步运用 Dagger笔记2 这个辅佐来替咱们编写模板代码。

3.1 @Componentappearance + @Inject

@Component 和 @Inject 是 Dagger2 最基础的两个注解,仅javahdxx运用这两个注解就能够完毕java环境变量装备最简略的依托注入。

  • @Component:创立一个 Dagger 容器,作为获取依托项的进口
@Component
publicappreciate interface ApplicatiappearonComponent {
UserRepositor公积金y userRepository();
}
  • @Inject:指示 Dagger 怎笔记本样实例化一个政策okhttp面试
public class UserRepositoryappointment {
private final UserLocalDataSource userLocalDataSource;
private final UserRemoteDataSource userRemoteDataS笔记本电脑开机黑屏没反应怎样办ource;
@Inject
pjava游戏ublic UserRepository(UserLocalDataSource userLocalDataSo宫外孕urce, UserRemoteDataSour笔记本电脑排名前十ce userRemoteDataSource) {
this.userLocalDataSource = userLocalDataSource;
this.userRemoteokhttp3下载DataSource = userRemoteDataSouapp装置下载rce;
}
}
---------------公积金借款----------okhttp3下载-------------------
public class UserLocalDataSource {
@Inject
public UserLocalDataSource() {
}
}
---------appear-----------------------------------
public class UserRemoveDataSjava怎样读ource {
@Inject
public UserRemoveDataSource() {
}
}

你需求用 @Inject 注解润饰依托项的结构办法,一同,它的依托项 UserLocalDatapproveaSource 和 UserRemoteDataSource 也需求添加 @Inject 注解。

以上代码在构建后会主动生成代码:

DaggerApplicationComponjava基础知识点entappstore.java

1、完毕 ApplicationComponent 接口
public final class DaggerApplicationCjavahdxxomponent implements Applicati笔记本cpu天梯图onComponeappreciatent {
private DaggerApplicationComponent() {
}
2、创立依托项实笔记例
@Override
public UserRepository userRepository() {
return new UserRepository(new UserLocalDataSapproachource(), new UserRemoteDataSource());
}
3、构建者模式
public static Builder builder() {
return new Builder();
}
public static ApplicationCompon工商银行ent create() {
return new Builder().build();
}okhttp长处
public static final class Builderapplication {
private Builder() {java面试题
}
public ApplicationComponent build() {
return new Daggokhttp运用erApplicationComponent();
}
}
}

能够看到,最简略的依托注入模板代码现已主动生成了。运用时,你只需求通过 ApplicationComponent 这个进口就可Go以取得 UserReopsitory 实例:

ApplicationComponent component = DaggerApplicationComponent.create();
UserRepository userRepository = component.userRepositorAPPy();

3.2 @Inject 字段注入

有些类不java环境变量装备是运用结构器初始化的,例如 Android 结构类 Activity 和java面试题 Fragmen宫颈癌疫苗t 由体系实例化,此刻就okhttp面试不能再运用 3.1 节 中运用的结构器java面试题注入,能够改为字段注入,并手动调用办法恳求注入。

结构器注入:(X)
public class MyActivity {
@Inject
public MyActivityjava怎样读(LoginViewModel viewModel){
...
}
}
--------------------------------------------
字段注入:
class MainActivjavahdxxity : AppCompatA笔记ctivity() {
@Inject
lateinit var viewModel: LoginVapproveiewModel
overr笔记ide fun onCreate(saapplicationvedInstanceState: Bundle?) {
DaggerApplicationComponent.create().inject001(this)
super.onCreate(savedInstanceState)
...
}
}
public class LoginViewModel {
private final UserReposokhttp封装itory userappointmentRepository;
@Inject
public LoginappearViewModel(UserRepojava言语sitory userRepository) {
this.userRepository = use宫颈癌疫苗rRepository;
}
}

在 Activity 或 Fragment 中运用时,需求留神公积金借款组件的生命周期:

  • 在 super.o龚俊nCreate() 中的康复阶段,Activity 会附加绑定的 Fragment,笔记本电脑排名前十这些 Fragmjava面试题ent 或许需求拜访公积金借款 Activity。为保证数据一致性,应在调用 super.onCreate() 之前在 Activity 的 onCreate() 办法中注入 Dagger。

  • 在运用 Fragment 时,应在 Fragment 的 onAttach() 办法中注入 Dagger,java面试题此操作能够在调用 super.onAttach() 之前或之后完毕。

3.3 @Singleton / @Scope

  • @Singleton / @Scope:声明效果域,能够捆绑依托项的效果域周期宫外孕
@Singleton
public cl笔记本电脑排名前十ass UserRappointmenteposijava基础知识点tory {
...
}
------------okhttp封装-------------------apple-------------
@Component
@Singleton
public inteappstorerface ApjavahdxxplappstoreicationComponent {
...
}

在 ApplicationComponent 和 UserRepository 上运用相同的效果域注解,okhttp运用过程标明两者处于同一工商银行个效果域周期。这意味着,同一个 Component 屡次供给该依笔记本电脑托项都是同一个实例。你能够直接运用内置的Go @Singleton,也能够运用自界说注解:

@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
--笔记本电脑性价比排行2020------------------------------------------
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomScope {}

提示: 运用 @Singleton 或 @MyappstoreCustomScope,效果是完全相同的。

以上代码在构建后会主动生成代码:

public final class DaggerApplicationComponent imp笔记本电脑性价比排行2020lements ApplicationComponent {google
private Provider&笔记lt;UserRepository> userRepositojava言语ryProvider;
private DaggerApplicationCjava基础知识点omponent() {
initialize(笔记本电脑怎样连wifi);
}
private vo公积金借款id initialize()笔记本电脑开不了机 {
this.userReposjava环境变量装备itoryProvjavascriptidapproacher = DoubleappearanceCheck.provider(UserRepository_Factory.create(UserLocalDataSource_Factorokhttp运用过程y.create(), UserRemoteDataSoappointmenturceokhttp3下载_Factory.create()));
}
@Override
publiappearancec UserRepository userRepository() {
return userRepositoryProvider.get();
}
...
}

效果域注解捆绑okhttp3源码剖析

有几个关于效果域注解的捆绑,你需求留神下:

  • 假定某个组件有效果域注解,那么该组件笔记只能给供给带有该注解appointment的类或许不带任何效果域注解的类;
  • 子组件不能运用和某个父组件的相同的效果域注解。

提示: 关于子组件的概笔记本电脑怎样连wifi念,你能够看 第 3.5 节

效果域注解标准

只需你满足上面提到的捆绑规矩,Dagger2 结构并笔记本电脑开机黑屏没反应怎样办不严厉捆绑你界说的效果域语义。你能够依照业okhttp面试务差异效果域,也能够依照生命周期差异效果域。例如:

依照事务差异approach:
@Singleton
@LoginScope
@RegisterScope
--------------------------------------------
按声明周期差异:
@SAPPingleton
@ActivityScope
@Modokhttp3源码剖析uleScope龚俊
@FeatureScope

不过appointment,依照生命周期差异效果域是愈加抱负的做法,效果域不应该清晰指明approach其完毕意图。

3.4 @Module + @Providers

  • @Module + @Providers枸杞:指示 Dagger 怎样实例化okhttp封装一个政策,但google不是以结构器的办法
publiokhttp面试答复c class UserRemoteDatappearanceaSourc笔记本电脑怎样连wifie {
privjavahdxxate final LoappearginRetrofitServijava怎样读ce loginRetrofitService;
@In宫颈癌ject
public UserRemoteDataSource(LoginRetrofitService loginRetrofitService) {
thokhttp长处is.loginRetrofitService = loginRetrofitService;
}
}
--------------------------------------------
@Module
public class NetworkModule {
@Provides
public LoginRetrofitService provide001(OkHttpClient client) {
return new Retrofit.Builder()
.baseUrl("https://example.com")
.build()
.createapproach(LoginService.class)java环境变量装备;
}
}
--appearance--approach----------------------------------------
@okhttp运用Singleton
@Component(modules = NetworkModule.class)
public interfaceokhttp运用过程 ApplicationComponent {
UserRepository u笔记本电脑什么牌子好serRepository();
void inject001(MainActivity activity);
}

@Mookhttp面试dule 模块供给了一种与 @Inject 不同的appear供给政策实例的办法。在 @Module 里,@Provides 办法的返回笔记本cpu天梯图值是依托项实例,而参数是进一步依托的政策。其他,你还需求在 @Component 参数中运用该模块。

目前为止,咱们结构的依托联络图如下所示:

Android | 从 Dagger2 到 Hilt 玩转依靠注入(一)

3.5 @Subcomponent

  • @Subcomponent:声明子组件,运用子组件的概念能够界说愈加详尽的效果域

子组件是承继并扩展父组件的政策图的组件,子组件中的政策就能够依托于父组件中供给的政策,但是父组件不能依托于子组件依托的政策(简略的包括联络,对吧?)。

咱们持续通过一个简略的比如来翻开:假定咱们有一个登录模块 L笔记本电脑oginActivity,它依托于 LoginModel。咱们的需求是界说一个子组件,它的声明周期只在一次登录流程中存在龚俊。在 第 3.2 节 提过,Ac笔记tivity 无法运用结构器注入,所以 LoginActivity 咱们选用的是 @Inject 字段注入的java游戏语法:

@Subcomponent
public interface LoginComponjava面试题ent {
void inject(LoginActivity activity);
}

但是这样界说的 LoginComponent 还不能真实称为某个组件的okhttp3源码剖析子组件,需求添加额外声明:

@Module(subcomponents = LoginComponent.class)
public class SubComponentsM枸杞oduokhttp源码解析le {
}
--------------------------------------------
@Component(modules = {NetworkModule.class,SubComponentsModule.class})
@Singleton
public interface ApplicationComponent {
UserRepository userRepository();
LoginCookhttp是干什么用的mponent.Factory loginCompon工商银行ent宫颈癌前期症状();
}
---------------------------------笔记-----------
@Subcomponent
public interfaceokhttp是干什么用的 LoginComponent {
@Subcomponent.Factory
interface Factory{
LoginCompappointmentonent create笔记本电脑开机黑屏没反应怎样办();
}
void inject001(LoginActivity activity);
}

在这里,咱们需求界说一个新模块 SubcomponentModule,一同需求在 LoginComponent 中界说okhttp长处子组件 Factory,以便 ApplicationComponent 知道怎样创立 LoginComponent 的示例。

现在,LoginComponent 就算声明完毕了。为了让 LoginComponent 坚持和 LoginActijavascriptvity 相同的生命周期,你应该在 LoginActivity 内部okhttp3源码剖析创立 Log宫颈癌前期症状inComponent 实例,并持有引证:

public class LoginActivity extgoogleends Activity {
1、持有子组件引证,保证相同工商银行生命周期
LoginComponent loginCoappointmentmponent;
2、@Inject 字段注入
@Inject
LoginViewModel lojava模拟器ginViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(appointmentsavedInstanceState);
3、创立子组件实例
loginComponent = ((MyApplication) getApplicatio工商银行nContext())
.appComponent.loginComponent().create();
4、注入
lo龚俊ginComponentjava游戏.injecjava模拟器t(this);
...
}
}

实施到过程 4 ,loginViewMo公积金借款del 字段就初始化完毕了。这里有一个需求特别留神的点,你考虑这个问题:假定你在 Logokhttp源码解析inActivapplicationity 中的一个 Fragment 重复注入 LoginViewModel,它是一个政策吗?

@SubcomponOKHttpent
publ枸杞ic interface LoginCojava环境变量装备mponent {
@Subcomponent.Factory
interface Factory {
LoginComponent create();
}appearance
void inject001(LoginActivity loginActi宫颈癌疫苗vity);
void inject002(LoginUsernameFragment fragment);
}

肯定是不同政策的,由于咱们还没有运用 第 3.3 节 提到的 @Singleapp装置下载ton / @Scope 效果域注解。现在咱们添加效果域注解:

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActiGovityScope {}
@ActivityScope
@Subcomp笔记本电脑怎样连wifioappointmentnent
pub笔记本电脑怎样连wifilic interface LoginComponent { ... }
@ActivityScope
public class LoginViewModel {
private final UserRepository userRepository;
@Inject
public LoginViewModel(UserRepository userRepository) {
this.userRepository = userRepository;
}
}

目前为止,咱们结构的依托联络图如下所示:

Android | 从 Dagger2 到 Hilt 玩转依靠注入(一)


4. 在 Dagger2 的基础上进行单元检验

当一个项目运用了 Dagger2 或许其它依托注入结构,那么在必定程度上它的各个组件之间是处于一种松耦合的状态,此刻进行单元检验显得游刃有余。

在 Dagger2 项目上你能够挑工商银行选在不同等级上注入模仿依托项:

4.1 政策等级:

你能够界说一个 FakeLoginViewModel,然后替换到 LoginActivity:

public classOKHttp LoginActivity extends Activity {
1、持有子组件引证,保appear证相同生命周期
LoginCompojava怎样读nent loginComponent;
2、@Injokhttp运用ect 字段注入
@Inject
FakeLoginViewModel loginViewModel;
}

4.2 组件等级

你可为为正式版和检验版界说两个组件:ApplicationComponent 和 TestAppli宫外孕cationComponent:

@Singleton
@Component(modules = {FakeNetworkModule.class, SubcomponentsModule.class})
public interfac宫颈癌e TestApplicationComponent extends ApplicationComponent {
}

5. 总结

总结一下咱们笔记本电脑提到的注解:

注解 描绘
@Comokhttp是干什么用的ponent 创立一个 Dagger 容器,作为获取依托项的进口
@Inject 指示 Dagger笔记本电脑怎样连wifi 怎样实例化Java一个政策
@Singleton / @Scope okhttp长处用域,能够捆绑依托项的效果域周期
@Module + @Prjava言语oviders 指示 Dagger 怎样实例化一个政策,但不是以结构器的办法
@笔记本Subcomponent 声明子组件,运用子组件的概念能够界说愈加详尽的效果域

参考资料

  • 【Dagger 官网】【Hilt 官网】【Daggeapplicationr2 Github】
  • 《Android 中的依托项注入》系列文档 —— Android Developers(必看)
  • 《Tasting Dagger 2 on Android.》 —— Fernando Cejas笔记
  • 《从java怎样读 Dagger 到笔记本 Hilt,谷歌为何执着于让咱们用依托注入?》 —— 扔物线 著
  • 《Jetpack 新成员,一篇文章带你玩转 Hilt 和依托注入》 —— 郭霖 著
  • 《Android Studio 4.1 的 Dagger 导航更新》 ——application Android Developers
  • 《在 Kgoogleotlin 中运用 Dagger 会遇到的圈套和优化办法》 —— Androijava游戏d Developers

创造不易,你的「三连」是丑丑最大的动力,我javascript们下次见!

Android | 从 Dagger2 到 Hilt 玩转依靠注入(一)