日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Dagger2 知识梳理(1) Dagger2 依赖注入的两种方式

發(fā)布時間:2025/7/14 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Dagger2 知识梳理(1) Dagger2 依赖注入的两种方式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、資料推薦

最近這幾天一直在看有關Dagger2有關的文章,感覺就是這東西真難用、真難懂,數(shù)次想要放棄,還好有網(wǎng)上大神的教程幫助,模模糊糊總算能把基本的幾個概念跑通了。

這里首先推薦 牛曉偉 的下面一系列文章,其將Dagger2的基本思想講的通俗易懂:

  • Android:dagger2 讓你愛不釋手 - 基礎依賴注入框架篇
  • Android:dagger2 讓你愛不釋手 - 重點概念講解、融合篇
  • Android:dagger2 讓你愛不釋手 - 終結篇

接下來是結合具體例子進行分析的兩篇文章,適合在理解基本思想的前提下對Dagger2有個更直觀的認識:

  • AItsuki 的 Dagger2 最清晰的使用教程
  • zFxiang_ 的 Dagger2 入門,以初學者角度

還有前同事 Johnny Shieh 的Dagger2系列,里面提到了后來新增的一些用法:

  • Dagger 2 完全解析(一),Dagger 2 的基本使用與原理
  • Dagger 2 完全解析(二),進階使用 Lazy、Qualifier、Scope 等
  • Dagger 2 完全解析(三),Component 的組織關系與 SubComponent
  • Dagger 2 完全解析(四),Android 中使用 Dagger 2
  • Dagger 2 完全解析(五),Kotlin 中使用 Dagger 2

了解完以上這些基礎文章,就可以嘗試去啃一下官方的英文文檔了,里面介紹了如何在Android中使用Dagger2,但是不得不說,寫的真是晦澀難懂,網(wǎng)上找了很久,也沒有把AndroidInjector說明白的:

  • Dagger & Android
  • User's Guide

雖然網(wǎng)上的例子很多,但是我們花了那么多時間去看這些文章,本質上還是要用到項目中,這里肯定要優(yōu)先推薦Google的官方架構Demo:todo-mvp-dagger2,這里面涉及到了很多新的注解用法。

二、導入依賴

在導入依賴的時候,需要考慮當前工程中使用的Gradle插件的版本。如果當前的插件版本小于2.2,那么需要引入 android-apt 插件,Dagger2 入門,以初學者角度 中就是用的這種方式。

在示例代碼中,根目錄下的build.gradle文件配置的Gradle插件版本為2.3.3:

因為大于2.2,所以我只需要在app模塊中的build.gradle文件中,引入以下兩個依賴就好了:

三、依賴注入的兩種方式

下面,我們用一個簡單的例子來演示使用Dagger2完成依賴注入的兩種方式:在進行數(shù)據(jù)的讀寫時,我們可以通過數(shù)據(jù)管理者DataRepository來管理數(shù)據(jù)源,外部通過調用這個數(shù)據(jù)倉庫提供的方法來讀寫數(shù)據(jù),完整的源碼可以查看 Dagger2Sample 中第一章。

對于這些數(shù)據(jù)源的賦值,就可以采用依賴注入的方式來實現(xiàn)。

  • DataRepository:目標類。
  • DataRepository內部的數(shù)據(jù)源:目標依賴類。

3.1 在目標依賴類構造函數(shù)上使用 @Inject

我們先看第一種方法,通過“在目標依賴類構造函數(shù)上使用@Inject,來完成依賴注入”。

第一步

先創(chuàng)建一個LocalSource表示本地的數(shù)據(jù)源,并在它構造函數(shù)上加上@Inject注解。這樣Dagger2在嘗試創(chuàng)建一個LocalSource對象賦值給DataRepository中的mLocalSource變量時,就會調用這個構造函數(shù)。

public class LocalSource {@Injectpublic LocalSource() {}public String getData() {return "使用在構造函數(shù)上使用 @Inject 的方式,獲取到了本地數(shù)據(jù)";} } 復制代碼

第二步

接下來需要聲明一個用@Component注解的接口或者抽象類,用于注入依賴,這個接口的方法名可以為任意值,但是其形參必須是目標類的具體類型,而返回值只能為void或者目標類的具體類型。

@Component public interface SourceComponent {public void inject(DataRepository dataRepository); } 復制代碼

第三步

做好前期這些準備,接下來需要按順序進行以下幾步操作:

  • 在目標類中需要被注入的變量上加上@Inject注解。
  • make一下工程,讓Dagger2根據(jù)SourceComponent中聲明的接口創(chuàng)建一個DaggerSourceComponent實現(xiàn)類。
  • 在需要注入的時候調用DaggerSourceComponent.create().inject(this)方法,完成依賴注入。

DataRepository文件如下所示:

public class DataRepository {@InjectLocalSource mLocalSource;public DataRepository() {DaggerSourceComponent.create().inject(this);}public String getData() {return mLocalSource.getData();}} 復制代碼

流程如下圖所示:

3.2 使用 @Module

3.1的實現(xiàn)方式有一個缺點,就是需要修改構造函數(shù),但是這對于一些第三方的對象來說是不可能做到的,此時就需要通過另一種方法來創(chuàng)建對象。

我們通過下面這個例子來演示:在DataRepository中實例化一個遠程數(shù)據(jù)源RemoteSource。

第一步

在RemoteSource的構造函數(shù)上不再需要添加@Inject注解:

public class RemoteSource {public String getData() {return "使用 @Module 的方式,獲取到了網(wǎng)絡數(shù)據(jù)";} } 復制代碼

第二步

接下來創(chuàng)建一個RemoteSourceModule類,用于提供RemoteSource對象。Dagger2會根據(jù)它聲明的方法的返回值類型去識別提供的是哪種類型的對象,這里有兩點需要注意:

  • 該Module類需要加上@Module注解
  • 提供RemoteSource的方法需要加上@Provides注解
@Module public class RemoteSourceModule {@Providespublic RemoteSource provideRemoteSource() {return new RemoteSource();} } 復制代碼

第三步

在SourceComponent中,我們需要告訴它哪些Module可以用來創(chuàng)建目標類所依賴的實例,這里和第一種方式的區(qū)別就是需要在@Component后面加上用來創(chuàng)建依賴實例的Module類名:

@Component(modules = {RemoteSourceModule.class}) public interface SourceComponent {public void inject(DataRepository dataRepository); } 復制代碼

第四步

而在目標類中,RemoteSource和LocalSource一樣,都需要加上@Inject注解:

public class DataRepository {@InjectLocalSource mLocalSource;@InjectRemoteSource mRemoteSource;public DataRepository() {DaggerSourceComponent.create().inject(this);}public String getData() {return mLocalSource.getData();}public String getNetData() {return mRemoteSource.getData();} } 復制代碼

流程如下圖所示:

3.3 Demo 演示

下面,我們用一個簡單的程序來驗證DataRepository中的mLocalSource/mRemoteSource是否注入成功:

public class RepositoryActivity extends AppCompatActivity {private static final String TAG = RepositoryActivity.class.getSimpleName();private Button mBtnGetData;private Button mBtnGetNetData;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_repository);mBtnGetData = (Button) findViewById(R.id.bt_get_data);mBtnGetData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {DataRepository repository = new DataRepository();String data = repository.getData();Toast.makeText(RepositoryActivity.this, data, Toast.LENGTH_SHORT).show();}});mBtnGetNetData = (Button) findViewById(R.id.bt_get_net_data);mBtnGetNetData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {DataRepository repository = new DataRepository();String data = repository.getNetData();Toast.makeText(RepositoryActivity.this, data, Toast.LENGTH_SHORT).show();}});} } 復制代碼

運行結果為:

3.4 依賴注入的過程

下面,我們來看一下依賴注入的內部實現(xiàn),整個依賴注入的入口函數(shù)為DaggerSourceComponent,在上面的例子中,它的源碼為:

public final class DaggerSourceComponent implements SourceComponent {private Provider<RemoteSource> provideRemoteSourceProvider;private MembersInjector<DataRepository> dataRepositoryMembersInjector;private DaggerSourceComponent(Builder builder) {assert builder != null;initialize(builder);}public static Builder builder() {return new Builder();}public static SourceComponent create() {return new Builder().build();}@SuppressWarnings("unchecked")private void initialize(final Builder builder) {this.provideRemoteSourceProvider =RemoteSourceModule_ProvideRemoteSourceFactory.create(builder.remoteSourceModule);this.dataRepositoryMembersInjector =DataRepository_MembersInjector.create(LocalSource_Factory.create(), provideRemoteSourceProvider);}@Overridepublic void inject(DataRepository dataRepository) {dataRepositoryMembersInjector.injectMembers(dataRepository);}public static final class Builder {private RemoteSourceModule remoteSourceModule;private Builder() {}public SourceComponent build() {if (remoteSourceModule == null) {this.remoteSourceModule = new RemoteSourceModule();}return new DaggerSourceComponent(this);}public Builder remoteSourceModule(RemoteSourceModule remoteSourceModule) {this.remoteSourceModule = Preconditions.checkNotNull(remoteSourceModule);return this;}} } 復制代碼

當我們調用靜態(tài)的create()方法后會返回一個DaggerSourceComponent實例,它是前面聲明的SourceComponent的實現(xiàn)類。其內部最關鍵的成員變量是DataRepository_MembersInjector類,它是依賴注入的實際執(zhí)行者,其內部包含了所有需要注入的實例的Provider,這些Provider是在構造時傳入的:

當我們調用DaggerSourceComponent的inject方法時,就會去調用DataRepository_MembersInjector類的injectMembers方法,它通過上面這兩個Provider所提供的get()方法對目標類中被@Inject注解的成員變量進行賦值:

3.5 依賴查找的過程

對于以上兩種依賴注入方法,其先后順序為:3.2 > 3.1,即Component先會在和它關聯(lián)的Module中尋找,這些關聯(lián)的Module包括:

  • 自己聲明的Module
  • 依賴的Component所關聯(lián)的Module
  • 通過@SubComponent繼承的Component關聯(lián)的Module

它會在以上三個維度中尋找Module是否提供了這個類的創(chuàng)建方法(也就是方法的返回值類型為這個類)

  • 如果有,那么就通過該方法創(chuàng)建,例如例子中的RemoteModule。
  • 如果沒有,那么再通過該類帶有@Inject注解標注的構造方法來創(chuàng)建,例如例子中的LocalSource。

對于每個目標依賴類,如果在它的創(chuàng)建過程中依賴于某個參數(shù),那么就需要先實例化這個參數(shù)。這就類似于二叉樹遍歷的過程,在這一遍歷過程中,如果出現(xiàn)了某個類型不能按照以上兩種方式實例化的時候,那么會在編譯時拋出異常。


更多文章,歡迎訪問我的 Android 知識梳理系列:

  • Android 知識梳理目錄:www.jianshu.com/p/fd82d1899…
  • 個人主頁:lizejun.cn
  • 個人知識總結目錄:lizejun.cn/categories/

總結

以上是生活随笔為你收集整理的Dagger2 知识梳理(1) Dagger2 依赖注入的两种方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。