Android Jetpack架構(gòu)組件(八)— Hilt

一、Hilt簡介

Hilt Google開源的一個 Android 的依賴注入庫蝶柿,其實是基于 Dagger鞠评。
Hilt 是專門為android打造的 ,可以使我們的代碼 盡量的簡化
Hilt 創(chuàng)建了一組標(biāo)準(zhǔn)的 組件和作用域剪芥。這些組件會自動集成到 Android 程序中的生命周期中垄开。在使用的時候可以指定使用的范圍,事件作用在對應(yīng)的生命周期當(dāng)中税肪。

1溉躲、依賴注入

Dependency Injection,簡稱DI寸认;
作用:使代碼解耦签财,便于復(fù)用,重構(gòu)和測試

類通常需要引用其他類偏塞,可通過以下三種方式獲取所需的對象:

  1. 在類中創(chuàng)建所需依賴項的實例
  2. 通過父類或其他類獲取
  3. 以參數(shù)形式提供唱蒸,可以在構(gòu)造類時提供這些依賴項,或者將這些依賴項傳入需要各個依賴項的函數(shù)

第三種方式就是依賴項注入

2灸叼、Android中的依賴注入方式

1.手動依賴注入
(1)神汹、構(gòu)造函數(shù)注入
//在構(gòu)造類時提供這些依賴項
class Car (private val driver: Driver) {
    fun run() {
        driver.run()
    }
}
val driver = Driver()
val car= Car(driver)
car.run()
(2)、字段注入(或 setter 注入)
//將依賴項傳入需要依賴項的函數(shù)
class Car {
    lateinit var driver: Driver
    fun run() = driver.run()
}
val car = Car()
val driver = Driver()
car.driver = driver
car.use()

上面兩種都是手動依賴項注入古今,但是如果依賴項和類過多屁魏,手動依賴注入就會產(chǎn)生一些問題:

1. 使用越來越繁瑣;
2. 產(chǎn)生大量模板代碼;
3. 必須按順序聲明依賴項;
4. 很難重復(fù)使用對象;
2.自動依賴注入框架

有一些庫通過自動執(zhí)行創(chuàng)建和提供依賴項的過程解決此問題捉腥,實現(xiàn)原理有如下幾種方案:

1. 通過反射氓拼,在運行時連接依賴項;
2. 通過注解,編譯時生成連接依賴項的代碼;
3. kotlin 強大的語法糖和函數(shù)式編程;
(1)抵碟、Dagger

Android領(lǐng)域最廣為熟知的依賴注入框架

  • Dagger 1.x版本:
    Square基于反射實現(xiàn)的桃漾,有兩個缺點一個是反射的耗時,另一個是反射是運行時的拟逮,編譯期不會報錯撬统。而使用難度較高,剛接觸時有經(jīng)常容易寫錯敦迄,造成開發(fā)效率底氛驮;
  • Dagger 2.x版本:
    Google基于Java注解實現(xiàn)的,完美解決了上述問題忙芒,
(2)叠萍、Koin

為 Kotlin 開發(fā)者提供的一個實用型輕量級依賴注入框架,采用純 Kotlin 語言編寫而成,僅使用功能解析,無代理、無代碼生成朽砰、無反射(通過kotlin 強大的語法糖(例如 Inline、Reified 等等)和函數(shù)式編程實現(xiàn))喉刘;

(3)瞧柔、Hilt

由于Dagger的復(fù)雜度和使用難度較大,Android團隊聯(lián)合Dagger2團隊睦裳,一起開發(fā)出來的一個專門面向Android的依賴注入框架Hilt造锅,最明顯的特征就是:1. 簡單;2. 提供了Android專屬的API廉邑;3. Google官方支持哥蔚,和Jetpack其他組件配合使用;

Hilt 通過為項目中的每個 Android 類提供容器并自動為您管理其生命周期蛛蒙,定義了一種在應(yīng)用中執(zhí)行 DI 的標(biāo)準(zhǔn)方法糙箍。
Hilt 在熱門 DI 庫 Dagger 的基礎(chǔ)上構(gòu)建而成,因而能夠受益于 Dagger 提供的編譯時正確性牵祟、運行時性能深夯、可伸縮性和 Android Studio 支持。

二诺苹、Hilt的使用

1咕晋、依賴版本配置

項目根build.gradle依賴

ext.kotlin_version = "1.5.0"http://kotlin版本
ext.hilt_version = '2.35'//hilt版本
repositories {
    google()
    mavenCentral()
}
dependencies {
    classpath "com.android.tools.build:gradle:4.2.1"
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    classpath 'com.google.dagger:hilt-android-gradle-plugin:2.35'
}

項目app中build.gradle依賴

implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"

項目模塊中build.gradle所使用插件

id 'kotlin-kapt'
id 'kotlin-android-extensions'

2、Hilt應(yīng)用

1.定義Hilt應(yīng)用類
  • 用@HiltAndroidApp注解Application;所有使用Hilt注入框架的應(yīng)用都必須包含一個帶有 @HiltAndroidApp 注釋的 Application 類收奔。
  • @HiltAndroidApp注解 會觸發(fā) Hilt 的代碼生成操作掌呜,生成的代碼包括應(yīng)用的一個基類,該基類充當(dāng)應(yīng)用級依賴項容器;
@HiltAndroidApp
class MyApplication : MultiDexApplication() {

}

然后坪哄,在AndroidManifest.xml中引入我們自定義的Application類质蕉。此時,生成的Hilt組件會附加到 Application 對象的生命周期翩肌,并為其提供依賴項模暗。此外,由于它也是應(yīng)用的父組件摧阅,所以其他組件可以訪問它提供的依賴項。

2.創(chuàng)建注入類

為了執(zhí)行字段注入绷蹲,需要在類的構(gòu)造函數(shù)中使用 @Inject 注解棒卷,以告知 Hilt 如何提供該類的實例

class Car @Inject constructor() {
    var name: String = ""

    fun run() {
    }
}

使用 @Inject 注釋執(zhí)行字段
@AndroidEntryPoint 會為項目中的每個 Android 類生成一個單獨的 Hilt 組件顾孽。這些組件可以從它們各自的父類接收依賴項, 如需從組件獲取依賴項,請使用 @Inject 注釋執(zhí)行字段注入比规, 注意:Hilt注入的字段是不可以聲明成private的若厚;

3.依賴項注入 Android 類

用@AndroidEntryPoint注釋類
目前支持6類入口點:Application(通過使用 @HiltAndroidApp),Activity蜒什,F(xiàn)ragment测秸,View,Service灾常,BroadcastReceiver

使用 @AndroidEntryPoint 注解 Android 類霎冯,還必須為依賴于該類的 Android 類添加注釋,例如為注解 fragment 钞瀑,則還必須為該 fragment 依賴的 Activity 添加@AndroidEntryPoint注釋沈撞。

@AndroidEntryPoint
class HiltActivity : AppCompatActivity() {
    @Inject
    lateinit var car: Car
}

注意:帶參數(shù)的依賴注入,需要構(gòu)造函數(shù)中所依賴的所有其他對象都支持依賴注入雕什;例如:Car的構(gòu)造函數(shù)有Engine缠俺,則Engine構(gòu)造函數(shù)也需要@Inject。

3贷岸、Hilt模塊

有時一些類型參數(shù)(如接口或來自外部庫的類)不能通過構(gòu)造函數(shù)注入壹士,對于這種情況,我們可以使用Hilt 模塊來向Hilt提供綁定信息偿警。

Hilt模塊是一個帶有@Module注釋的類躏救,并使用 @InstallIn 設(shè)置作用域。與Dagger模塊的作用一樣户敬,它會告知Hilt如何提供某些類型的實例落剪。與Dagger模塊不同的是,我們必須使用@InstallIn注解為Hilt模塊添加注釋尿庐,以告知Hilt模塊將用在哪個Android類中忠怖。

1.@Binds注入接口

由于Phone是一個接口,無法通過構(gòu)造函數(shù)注入Hilt抄瑟,而應(yīng)向Hilt提供綁定信息凡泣。即在Hilt模塊內(nèi)創(chuàng)建一個帶有@Binds注釋的抽象函數(shù)。

通常皮假,帶有注釋的函數(shù)會向Hilt提供以下信息:

  1. 函數(shù)返回類型會告知Hilt函數(shù)提供的是哪個接口的實例鞋拟。
  2. 函數(shù)參數(shù)會告知Hilt需要提供哪種實現(xiàn)。
//1. 接口
interface Phone {
    fun call()
}
//2. 實現(xiàn)類
class Huawei @Inject constructor() : Phone {
    override fun call() {
    }
}
//3. 被注入的類惹资,入?yún)⑹墙涌陬愋?class People @Inject constructor(val phone: Phone) {
    fun call() {
        phone.call()
    }
}
//4. 使用@Binds注入接口實例
@Module
@InstallIn(ActivityComponent::class)
abstract class PhoneModel {
    @Binds
    abstract fun bindPhone(phone: Huawei): Phone
}
//5. 使用注入的實例
@AndroidEntryPoint
class HiltActivity : AppCompatActivity() {
    @Inject
    lateinit var people: People

    fun test() {
        people.phone.call()
    }
}

由于PhoneModel 帶有 @InstallIn(ActivityComponent.class) 注釋贺纲,因為我們可以將該依賴項注入Activity中。并且褪测,PhoneModel中的所有依賴項都可以在所有Activity中使用猴誊。

2.@Provides注入實例

如果某個類不歸您所有(因為它來自外部庫潦刃,如 Retrofit、OkHttpClient 或 Room 數(shù)據(jù)庫等類)懈叹,或者必須使用構(gòu)建器模式創(chuàng)建實例乖杠,也無法通過構(gòu)造函數(shù)注入。

這種情況注入方法是在Hilt模塊內(nèi)創(chuàng)建一個函數(shù)澄成,然后使用@Provides為該函數(shù)添加注釋胧洒。

帶有注釋的函數(shù)會向 Hilt 提供以下信息:

  1. 函數(shù)返回類型會告知 Hilt 函數(shù)提供哪個類型的實例。
  2. 函數(shù)參數(shù)會告知 Hilt 相應(yīng)類型的依賴項墨状。
  3. 函數(shù)主體會告知 Hilt 如何提供相應(yīng)類型的實例卫漫。每當(dāng)需要提供該類型的實例時,Hilt 都會執(zhí)行函數(shù)主體歉胶。
@Module
@InstallIn(SingletonComponent::class)
class DINetworkModule {

    /**
     * [OkHttpClient]依賴提供方法
     *
     * @return OkHttpClient
     */
    @Singleton
    @Provides
    fun provideOkHttpClient(): OkHttpClient {
        // 日志攔截器部分
        val level = if (BuildConfig.VERSION_TYPE != VersionStatus.RELEASE) BODY else NONE
        val logInterceptor = HttpLoggingInterceptor().setLevel(level)

        return OkHttpClient.Builder()
            .retryOnConnectionFailure(true)
            .connectTimeout(15L * 1000L, TimeUnit.MILLISECONDS)
            .readTimeout(20L * 1000L, TimeUnit.MILLISECONDS)
            .writeTimeout(20L * 1000L, TimeUnit.MILLISECONDS)
            .addInterceptor(logInterceptor)
//            .addInterceptor(CookiesInterceptor())
            .build()
    }

    /**
     * 項目主要服務(wù)器地址的[Retrofit]依賴提供方法
     *
     * @param okHttpClient OkHttpClient OkHttp客戶端
     * @return Retrofit
     */
    @Singleton
    @Provides
    fun provideMainRetrofit(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl(HttpBaseUrlConstant.BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(okHttpClient)
            .build()
    }
}
3.限定符
  • 限定符也是一種注解汛兜,當(dāng)為某個類型定義了多個綁定時,我們可以使用它來標(biāo)識該類型的特定綁定通今。
  • 使用@Qualifier注解實現(xiàn)限定符粥谬。
3.1為同一類型提供多個綁定

如果需要讓Hilt以依賴項的形式提供同一類型的不同實現(xiàn),那么必須向 Hilt 提供多個綁定辫塌,同一類型定義多個綁定可以使用限定符來實現(xiàn)漏策。

//1. 接口和實現(xiàn)類
interface Phone {
    fun call()
}

class Huawei @Inject constructor() : Phone {
    override fun call() {
    }
}

class Xiaomi @Inject constructor() : Phone {
    override fun call() {
    }
}

//2. 創(chuàng)建多個類型的注解
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class BindHuawei

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class BindXiaomi

//@Retention:注解的生命周期
//AnnotationRetention.SOURCE:僅編譯期,不存儲在二進制輸出中
//AnnotationRetention.BINARY:存儲在二進制輸出中臼氨,但對反射不可見
//AnnotationRetention.RUNTIME:存儲在二進制輸出中掺喻,對反射可見


//3. 在Hilt模塊中使用注解
@Module
@InstallIn(ActivityComponent::class)
abstract class PhoneModel {
    @BindHuawei
    @Binds
    abstract fun bindHuawei(cpu: Huawei): Phone

    @ BindXiaomi
    @Binds
    abstract fun bindXiaomi(cpu: Xiaomi): Phone
}

//4. 使用依賴注入獲取實例,可以用在字段注解储矩,也可以用在構(gòu)造函數(shù)或者方法入?yún)⒅?@AndroidEntryPoint
class HiltActivity : AppCompatActivity() {
    @BindHuawei
    @Inject
    lateinit var huawei: Phone

    @BindXiaomi
    @Inject
    lateinit var xiaomi: Phone

    fun use() {
        huawei.call()
        xiaomi.call()
    }
}

如果需要向某個類型添加限定符感耙,那么應(yīng)該向提供該依賴項的所有可能的渠道都添加限定符。這是因為讓基本的實現(xiàn)或通用的實現(xiàn)在不帶限定符的情況下避免出錯持隧,也是為了避免導(dǎo)致Hilt注入錯誤的依賴項即硼。

3.2Hilt中的預(yù)定義限定符

Hilt提供了一些預(yù)定義的限定符。
Hilt 提供的@ApplicationContext 和 @ActivityContext 限定符用來獲取Context 類

class ModuleOne @Inject constructor(@ApplicationContext private val context: Context)

class ModuleTwo @Inject constructor(@ActivityContext private val context: Context)

對于Application和Activity這兩個類型屡拨,Hilt也是給它們預(yù)置好了注入功能(必須是這兩個只酥,即使子類也不可以)

class ModuleOne @Inject constructor(val application: Application)

class ModuleTwo @Inject constructor(val activity: Activity)

4、Hilt內(nèi)置組件類型

@Module:將這個類注冊為module
@InstallIn():把這個模塊安裝到哪個組件中

Hilt內(nèi)置了7種組件可選:
  1. SingletonComponent(ApplicationComponent廢棄):
    對應(yīng)Application呀狼,依賴注入實例可以在全項目中使用
  2. ActivityRetainedComponent:
    對應(yīng)ViewModel(在配置更改后仍然存在裂允,因此它在第一次調(diào)用 Activity#onCreate() 時創(chuàng)建,在最后一次調(diào)用 Activity#onDestroy() 時銷毀)
  3. ActivityComponent:
    對應(yīng)Activity哥艇,Activity中包含的Fragment和View也可以使用绝编;
  4. FragmentComponent:
    對應(yīng)Fragment
  5. ViewComponent:
    對應(yīng)View
  6. ViewWithFragmentComponent:
    對應(yīng)帶有 @WithFragmentBindings 注釋的 View
  7. ServiceComponent:
    對應(yīng)Service
Hilt內(nèi)置7種組件作用域注解:
  1. @Singleton:
    對應(yīng)組件ApplicationComponent,整個項目共享同一個實例
  2. @ActivityRetainedScope:
    對應(yīng)組件ActivityRetainedComponent
  3. @ActivityScoped:
    對應(yīng)組件ActivityComponent,在同一個Activity(包括其包含的Fragment和View中)內(nèi)部將會共享同一個實例
  4. @FragmentScoped:
    對應(yīng)組件FragmentComponent
  5. @ViewScoped:
    對應(yīng)組件ViewComponent和ViewWithFragmentComponent十饥;
  6. @ServiceScopedService:
    對應(yīng)ServiceComponent
組件的層次結(jié)構(gòu)怎棱。

將Hilt模塊安裝到組件后,其綁定就可以與其他綁定的依賴項相互發(fā)生作用了绷跑,也可以用作組件層次結(jié)構(gòu)中該組件下的任何子組件中其他綁定的依賴項。


組件的層次結(jié)構(gòu)
組件

注意:ApplicationComponent廢棄凡资,改為SingletonComponent

5砸捏、ViewModel的依賴注入

ViewModel中創(chuàng)建Repository并在Activity中使用

//1. 倉庫層
class Repository @Inject constructor(){
    @Inject
    lateinit var apiService: ApiService
    suspend fun requestInfo(): RepoResponse {
        return apiService.requestInfo()
    }
}
//2. ViewModel層
@ActivityRetainedScoped
class MyViewModel @Inject constructor(private val repository: Repository): ViewModel() {
    var ld_result: MutableLiveData<String> = MutableLiveData()
    fun requestInfo() {
        viewModelScope.launch {
            runCatching {
                withContext(Dispatchers.IO){
                    repository. requestInfo()
                }
            }.onSuccess {
                ld_result.value=gson().toJson(it).toString()
            }.onFailure {
                ld_result.value=it.message
            }
        }
    }
}
//3. Activity層
@AndroidEntryPoint
class HiltActivity : AppCompatActivity() {

    @Inject
    lateinit var viewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_hilt)
        viewModel.ld_result.observe(this, Observer {

        })
        viewModel. requestInfo()
    }
}
@HiltViewModel注解ViewModel

Hilt專門為其提供了一種獨立的依賴注入方式: @HiltViewModel來獲取ViewModel實例。

//1. 倉庫層
class CommonRepository @Inject constructor() : BaseRepository() {

    @Inject
    lateinit var mApi: HomeApiService

    suspend fun requestHome(
        callback: RequestCallback<HomeBean>
    ) = request(callback) { mApi.requestHome() }

}

//2. ViewModel層
@HiltViewModel
class HomeViewModel @Inject constructor(private val mRepository: CommonRepository) :
    BaseViewModel() {

}

//3. Activity層
@AndroidEntryPoint
class MainActivity : BaseActivity<ActivityMainLayoutBinding, HomeViewModel>() {

    val mViewModel: HomeViewModel by viewModels()
//  或  val mViewModel: HomeViewModel by lazy { ViewModelProvider(this).get(HomeViewModel::class.java) }
 
}
SavedStateHandle 和 @assist注解

Activity/Fragment被銷毀一般有三種情況:

  1. 界面關(guān)閉或退出應(yīng)用
  2. Activity 配置 (configuration) 被改變隙赁,如旋轉(zhuǎn)屏幕時垦藏;
  3. 在后臺時因運行內(nèi)存不足被系統(tǒng)回收;

ViewModel 會處理2的情況伞访,而3的情況就需要使用onSaveInstanceState()保存數(shù)據(jù)掂骏,重建時用SavedStateHandle恢復(fù)數(shù)據(jù),就要用@assist 注解添加 SavedStateHandle 依賴項

@HiltViewModel
class HomeViewModel @Inject constructor(private val mRepository: CommonRepository,
    //SavedStateHandle 用于進程被終止時厚掷,保存和恢復(fù)數(shù)據(jù)
    @Assisted private val savedStateHandle: SavedStateHandle
) ) : BaseViewModel() {
    var ld_result: MutableLiveData<String> = MutableLiveData()
    private val userId: MutableLiveData<String> = savedStateHandle.getLiveData("userId")

    
}

6弟灼、Hilt不支持的注入依賴項

Hilt支持一些最常見的 Android 類,如Application冒黑、Activity田绑、Fragment、View抡爹、Service和BroadcastReceiver掩驱。如果要在Hilt不支持的類中執(zhí)行字段注入:

  • 可以使用 @EntryPoint 注釋創(chuàng)建入口點, 調(diào)用EntryPointAccessors的靜態(tài)方法來獲得自定義入口點的實例,入口點是由Hilt管理的代碼與并非由Hilt管理的代碼之間的邊界冬竟,它是代碼首次進入Hilt所管理對象的圖的位置欧穴,入口點允許Hilt使用它并不管理的代碼提供依賴關(guān)系圖中的依賴項。
  • EntryPointAccessors提供了四個靜態(tài)方法:fromActivity泵殴、fromApplication涮帘、fromFragment、fromView袋狞,根據(jù)自定義入口的MyEntryPoint的注解@InstallIn所指定的范圍選擇對應(yīng)的獲取方法焚辅;
//1、注冊創(chuàng)建入口點
@EntryPoint
@InstallIn(ApplicationComponent::class)
interface MyEntryPoint{
    fun getRetrofit():Retrofit
}
//2苟鸯、使用EntryPointAccessors獲取實例
Context appContext = getContext().getApplicationContext();
MyEntryPoint hiltEntryPoint =EntryPointAccessors.fromApplication(appContext, MyEntryPoint.class);
Retrofit retrofit = hiltEntryPoint. getRetrofit();

參數(shù)是組件實例或充當(dāng)組件持有者的 @AndroidEntryPoint 對象同蜻,使用時以參數(shù)形式傳遞的組件和 EntryPointAccessors 靜態(tài)方法都與 @EntryPoint 接口上的 @InstallIn 注釋中的 Android 類匹配。

在本例中早处,我們使用 ApplicationContext 作為檢索入口點湾蔓,因為入口點安裝在 ApplicationComponent 中。如果需要檢索的綁定位于 ActivityComponent 中那么改為 ActivityContext即可砌梆。

7默责、Hilt注入ContentProvider

  • Hilt支持的入口點中少了一個關(guān)鍵的Android組件:ContentProvider, 主要原因就是ContentProvider.onCreate() 在Application的onCreate() 之前執(zhí)行贬循,因此很多人會利用這個特性去進行提前初始化, 詳見Android Jetpack系列--5. App Startup使用詳解, 而Hilt的工作原理是從Application.onCreate()中開始的,即ContentProvider.onCreate()執(zhí)行之前桃序,Hilt的所有功能都還無法正常工作杖虾;
class MyContentProvider : ContentProvider() {
    override fun onCreate(): Boolean {
        context?.let {
            val appContext=it.applicationContext
            //調(diào)用EntryPointAccessors.fromApplication()函數(shù)來獲得自定義入口點的實例
            val entryPoint=EntryPointAccessors.fromApplication(appContext,MyEntryPoint::class.java)
            //再調(diào)用入口點中定義的getRetrofit()函數(shù)就能得到Retrofit的實例
            val retrofit=entryPoint.getRetrofit()
        }
        return true
    }
}

8、Hilt注入Startup

App Startup 會默認(rèn)提供一個 InitializationProvider媒熊,InitializationProvider 繼承 ContentProvider奇适;

class LjyInitializer : Initializer<Unit> {
    override fun create(context: Context) {
        //調(diào)用EntryPointAccessors.fromApplication()函數(shù)來獲得自定義入口點的實例
        val entryPoint= EntryPointAccessors.fromApplication(context, MyEntryPoint::class.java)
        //再調(diào)用入口點中定義的getRetrofit()函數(shù)就能得到Retrofit的實例
        val retrofit=entryPoint.getRetrofit()
        LjyLogUtil.d("retrofit:$retrofit")
    }

    override fun dependencies(): List<Class<out Initializer<*>>> {
        return emptyList()
    }
}

報錯解決:

Expected @HiltAndroidApp to have a value. Did you forget to apply the Gradle Plugin?

android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation":
                             "$projectDir/schemas".toString()]
            }
        }
    }
}

9、Hilt注入WorkManager

使用Hilt注入WorkManager芦鳍,需要在Gradle文件中添加如下一些額外的依賴項

dependencies {
  implementation 'androidx.hilt:hilt-work:1.0.0-alpha01'
  // Kotlin.
  kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
  // Java.
  annotationProcessor 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
}

首先嚷往,在Worker對象的構(gòu)造函數(shù)中使用@WorkerInject注解來注入一個 Worker,然后在 Worker對象中使用@Singleton或未限定作用域的綁定對象的作用域柠衅,還必須使用 @Assisted 為 Context 和 WorkerParameters 依賴項添加注釋皮仁。

public class ExampleWorker extends Worker {

  private final WorkerDependency workerDependency;

  @WorkerInject
  ExampleWorker(
    @Assisted @NonNull Context context,
    @Assisted @NonNull WorkerParameters params,
    WorkerDependency workerDependency
  ) {
    super(context, params);
    this.workerDependency = workerDependency;
  }
  ...
}

然后,讓Application類實現(xiàn)Configuration.Provider接口菲宴,注入HiltWorkFactory 的實例贷祈,并將其傳入WorkManager配置,如下所示喝峦。

@HiltAndroidApp
public class ExampleApplication extends Application implements Configuration.Provider {

  @Inject HiltWorkerFactory workerFactory;

  @Override
  public Configuration getWorkManagerConfiguration() {
    return Configuration.Builder()
             .setWorkerFactory(workerFactory)
             .build();
  }
}

參考:
Android Jetpack--Hilt使用詳解
Android Jetpack架構(gòu)組件(十二)之Hilt

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末付燥,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子愈犹,更是在濱河造成了極大的恐慌键科,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,222評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件漩怎,死亡現(xiàn)場離奇詭異勋颖,居然都是意外死亡,警方通過查閱死者的電腦和手機勋锤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評論 3 385
  • 文/潘曉璐 我一進店門饭玲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人叁执,你說我怎么就攤上這事茄厘。” “怎么了谈宛?”我有些...
    開封第一講書人閱讀 157,720評論 0 348
  • 文/不壞的土叔 我叫張陵次哈,是天一觀的道長。 經(jīng)常有香客問我吆录,道長窑滞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,568評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮哀卫,結(jié)果婚禮上巨坊,老公的妹妹穿的比我還像新娘。我一直安慰自己此改,他們只是感情好趾撵,可當(dāng)我...
    茶點故事閱讀 65,696評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著共啃,像睡著了一般鼓寺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上勋磕,一...
    開封第一講書人閱讀 49,879評論 1 290
  • 那天,我揣著相機與錄音敢靡,去河邊找鬼挂滓。 笑死,一個胖子當(dāng)著我的面吹牛啸胧,可吹牛的內(nèi)容都是我干的赶站。 我是一名探鬼主播,決...
    沈念sama閱讀 39,028評論 3 409
  • 文/蒼蘭香墨 我猛地睜開眼纺念,長吁一口氣:“原來是場噩夢啊……” “哼贝椿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起陷谱,我...
    開封第一講書人閱讀 37,773評論 0 268
  • 序言:老撾萬榮一對情侶失蹤烙博,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后烟逊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體渣窜,經(jīng)...
    沈念sama閱讀 44,220評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,550評論 2 327
  • 正文 我和宋清朗相戀三年宪躯,在試婚紗的時候發(fā)現(xiàn)自己被綠了乔宿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,697評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡访雪,死狀恐怖详瑞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情臣缀,我是刑警寧澤坝橡,帶...
    沈念sama閱讀 34,360評論 4 332
  • 正文 年R本政府宣布,位于F島的核電站精置,受9級特大地震影響驳庭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,002評論 3 315
  • 文/蒙蒙 一饲常、第九天 我趴在偏房一處隱蔽的房頂上張望蹲堂。 院中可真熱鬧,春花似錦贝淤、人聲如沸柒竞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,782評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朽基。三九已至,卻和暖如春离陶,著一層夾襖步出監(jiān)牢的瞬間稼虎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,010評論 1 266
  • 我被黑心中介騙來泰國打工招刨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留霎俩,地道東北人。 一個月前我還...
    沈念sama閱讀 46,433評論 2 360
  • 正文 我出身青樓沉眶,卻偏偏與公主長得像打却,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子谎倔,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,587評論 2 350

推薦閱讀更多精彩內(nèi)容