Dagger Hilt 初探

介紹

Dagger Hilt (這名字起的溜...........)

官方描述其設(shè)計(jì)目的:

  • To simplify Dagger-related infrastructure for Android apps.
  • To create a standard set of components and scopes to ease setup, readability/understanding, and code sharing between apps.
  • To provide an easy way to provision different bindings to various build types (e.g. testing, debug, or release).

簡(jiǎn)單說就是Dagger Android的瘦身包了牛,使依賴注入在Android開發(fā)中標(biāo)準(zhǔn)化介粘、簡(jiǎn)單化簿透。

集成

首先在項(xiàng)目級(jí)別的build.gradle文件中添加以下內(nèi)容馆揉,這將使我們能夠訪問hilt gradle插件:

classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'

然后在應(yīng)用程序級(jí)別的build.gradle文件并應(yīng)用此插件:

apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'

最后喻旷,在應(yīng)用程序級(jí)別build.gradle文件中添加所需的hilt依賴項(xiàng):

implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01'
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'

這樣Hilt就可以使用了洽沟。

Hilt Application

按照官方要求慎璧,首先需要在自定義的Application類中添加@HiltAndroidApp注解:

@HiltAndroidApp
class APP:Application()

這有什么作用?以下來自官方描述:

All apps using Hilt must contain an Application class annotated with @HiltAndroidApp. @HiltAndroidApp kicks off the code generation of the Hilt components and also generates a base class for your application that uses those generated components. Because the code generation needs access to all of your modules, the target that compiles your Application class also needs to have all of your Dagger modules in its transitive dependencies.

Just like other Hilt Android entry points, Applications are members injected as well. This means you can use injected fields in the Application after super.onCreate() has been called.

Daager2中蹋辅,需要Application繼承DaggerApplication,并且還需要?jiǎng)?chuàng)建Application的Module亡蓉。
這里只需要使用@HiltAndroidApp的注解就可以完成對(duì)Application的依賴注入晕翠,由Hilt gradle插件生成對(duì)應(yīng)的文件

構(gòu)建后我們看到在 app/build/generated/source/kapt/debug/目錄下生成了一個(gè)Hilt_APP的抽象類:

/**
 * A generated base class to be extended by the @dagger.hilt.android.HiltAndroidApp annotated class. If using the Gradle plugin, this is swapped as the base class via bytecode transformation. */
@Generated("dagger.hilt.android.processor.internal.androidentrypoint.ApplicationGenerator")
public abstract class Hilt_APP extends Application implements GeneratedComponentManager<Object> {
  private final ApplicationComponentManager componentManager = new ApplicationComponentManager(new ComponentSupplier() {
    @Override
    public Object get() {
      return DaggerAPP_HiltComponents_ApplicationC.builder()
          .applicationContextModule(new ApplicationContextModule(Hilt_APP.this))
          .build();
    }
  });

  protected final ApplicationComponentManager componentManager() {
    return componentManager;
  }

  @Override
  public final Object generatedComponent() {
    return componentManager().generatedComponent();
  }

  @CallSuper
  @Override
  public void onCreate() {
    // This is a known unsafe cast, but is safe in the only correct use case:
    // APP extends Hilt_APP
    ((APP_GeneratedInjector) generatedComponent()).injectAPP(UnsafeCasts.<APP>unsafeCast(this));
    super.onCreate();
  }
}

  • ApplicationComponentManager的聲明
  • onCreate函數(shù)中注入Application類

看下里面涉及到的~

ApplicationComponentManager

public final class ApplicationComponentManager implements GeneratedComponentManager<Object> {
  private volatile Object component;
  private final Object componentLock = new Object();
  private final ComponentSupplier componentCreator;

  public ApplicationComponentManager(ComponentSupplier componentCreator) {
    this.componentCreator = componentCreator;
  }

  @Override
  public Object generatedComponent() {
    if (component == null) {
      synchronized (componentLock) {
        if (component == null) {
          component = componentCreator.get();
        }
      }
    }
    return component;
  }
}

主要用于管理應(yīng)用程序中的Hilt Component的創(chuàng)建

  • 構(gòu)造中創(chuàng)建ComponentSupplier實(shí)例。

  • generatedComponent():通過對(duì)象鎖獲取ComponentSupplier類中的Object砍濒,并負(fù)責(zé)在onCreate函數(shù)中將依賴項(xiàng)注入到我們的應(yīng)用程序類中淋肾。

ComponentSupplier

提供component的接口

/**
 * Interface for supplying a component. This is separate from the Supplier interface so that
 * optimizers can strip this method (and therefore all the Dagger code) from the main dex even if a
 * Supplier is referenced in code kept in the main dex.
 */
public interface ComponentSupplier {
  Object get();
}

ApplicationC

代碼比較長(zhǎng)就不貼出來了,看下builder:

import dagger.hilt.android.internal.builders.ActivityComponentBuilder;
import dagger.hilt.android.internal.builders.ActivityRetainedComponentBuilder;
import dagger.hilt.android.internal.builders.FragmentComponentBuilder;
import dagger.hilt.android.internal.builders.ServiceComponentBuilder;
import dagger.hilt.android.internal.builders.ViewComponentBuilder;
import dagger.hilt.android.internal.builders.ViewWithFragmentComponentBuilder;

ComponentSupplier實(shí)現(xiàn)的內(nèi)部爸邢,我們可以看到對(duì)ApplicationC(Application組件)類的引用樊卓。DaggerAPP_HiltComponents_ApplicationC是生成的應(yīng)用程序組件,它充當(dāng)Hilt在我們的應(yīng)用程序中使用的(Activity杠河,F(xiàn)ragment碌尔,Service,View等組件)的全局容器券敌。

GeneratedInjector

@OriginatingElement(
    topLevelClass = APP.class
)
@GeneratedEntryPoint
@InstallIn(ApplicationComponent.class)
@Generated("dagger.hilt.android.processor.internal.androidentrypoint.InjectorEntryPointGenerator")
public interface APP_GeneratedInjector {
  void injectAPP(APP aPP);
}

接口類提供injectAPP方法為外部類提供了一個(gè)訪問點(diǎn)唾戚,以觸發(fā)應(yīng)用程序Component的注入。

ApplicationContextModule

@Module
@InstallIn(ApplicationComponent.class)
public final class ApplicationContextModule {
  private final Context applicationContext;

  public ApplicationContextModule(Context applicationContext) {
    this.applicationContext = applicationContext;
  }

  @Provides
  @ApplicationContext
  Context provideContext() {
    return applicationContext;
  }

  @Provides
  Application provideApplication() {
    return (Application) applicationContext.getApplicationContext();
  }

}

主要是提供ApplicationContext待诅,通過@InstalIIn注入到 ApplicationComponent便于后續(xù)使用

這里有個(gè)@ApplicationContext 這是個(gè)qualifers 限定符叹坦,Hilt還提供了一個(gè)@ActivityContext

例如:

class AnalyticsAdapter @Inject constructor(
    @ActivityContext private val context: Context,
    private val service: AnalyticsService
) { ... }
@Singleton
class NetWorkUtils @Inject constructor(@ApplicationContext private val context: Context) {
    fun isNetworkConnected(): Boolean {
        .....
    }
}

可以直接作為@Provides方法或@Inject構(gòu)造的參數(shù)使用卑雁。

流程

image

Hilt Components

介紹

在之前Dagger-Android中募书,我們必須創(chuàng)建諸如ActivityScope,F(xiàn)ragmentScope之類的范圍注釋测蹲,以管理對(duì)象的生命周期莹捡,

而這里只要使用@InstallIn的注解,就可以委托Hilt幫我們管理

組件的生存期:

組件 范圍 創(chuàng)建 銷毀
ApplicationComponent @Singleton Application#onCreate() Application#onDestroy()
ActivityRetainedComponent @ActivityRetainedScope Activity#onCreate()鏈接 Activity#onDestroy()鏈接
ActivityComponent @ActivityScoped Activity#onCreate() Activity#onDestroy()
FragmentComponent @FragmentScoped Fragment#onAttach() Fragment#onDestroy()
ViewComponent @ViewScoped View#super() View 被毀
ViewWithFragmentComponent @ViewScoped View#super() View 被毀
ServiceComponent @ServiceScoped Service#onCreate() Service#onDestroy()

@InstallIn模塊中確定綁定范圍時(shí)扣甲,綁定上的范圍必須與component范圍匹配篮赢。例如,@InstallIn(ActivityComponent.class)模塊內(nèi)的綁定只能用限制范圍@ActivityScoped文捶。

例如我們需要在App中共享OkHttp的配置:

@Module
@InstallIn(ApplicationComponent::class)
class ApplicationModule {

    @Provides
    fun provideBaseUrl() = "...."

    @Provides
    @Singleton
    fun provideOkHttpClient() = if (BuildConfig.DEBUG) {
        val loggingInterceptor = HttpLoggingInterceptor()
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
        OkHttpClient.Builder()
            .addInterceptor(loggingInterceptor)
            .build()
    } else OkHttpClient
        .Builder()
        .build()


    @Provides
    @Singleton
    fun provideRetrofit(
        okHttpClient: OkHttpClient,
        BASE_URL: String
    ): Retrofit =
        Retrofit.Builder()
            .addConverterFactory(MoshiConverterFactory.create())
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .build()

    @Provides
    @Singleton
    fun provideApiService(retrofit: Retrofit): ApiService = retrofit.create(ApiService::class.java)

}

類似Dagger中:

@Module
class NetworkModule {
        // Hypothetical dependency on LoginRetrofitService
        @Provides
        fun provideLoginRetrofitService(
            okHttpClient: OkHttpClient
        ): LoginRetrofitService { ... }
}

@Component(modules = [NetworkModule::class])
interface ApplicationComponent {
        ...
}

這里通過@InstallIn(ApplicationComponent::class)Hilt幫我們管理ApplicationModule的生命周期

Module

module的使用基本和dagger中一樣, 用來提供一些無法用構(gòu)造@Inject的依賴, 比如接口, 第三方庫類型, Builder模式構(gòu)造的對(duì)象等.

  • @Module: 標(biāo)記一個(gè)module, 可以是一個(gè)object.
  • @Provides: 標(biāo)記方法, 提供返回值類型的依賴.這里就不需要手動(dòng)添加到@Component(modules = ...)
  • @Binds: 標(biāo)記抽象方法, 返回接口類型, 接口實(shí)現(xiàn)是方法的唯一參數(shù).
interface AnalyticsService {
  fun analyticsMethods()
}

// Constructor-injected, because Hilt needs to know how to
// provide instances of AnalyticsServiceImpl, too.
class AnalyticsServiceImpl @Inject constructor(
  ...
) : AnalyticsService { ... }

@Module
@InstallIn(ActivityComponent::class)
abstract class AnalyticsModule {

  @Binds
  abstract fun bindAnalyticsService(
    analyticsServiceImpl: AnalyticsServiceImpl
  ): AnalyticsService
}

@Provides@Binds的區(qū)別:

按照官方說@Binds需要module是一個(gè)abstract class,@Provides需要module是一個(gè)object.而且@Binds需要在方法參數(shù)里面明確指明接口的實(shí)現(xiàn)類

但是@Provides這么用也是可以的荷逞。

Qualifier

如果要提供同一個(gè)接口的不同實(shí)現(xiàn), 可以用不同的注解來標(biāo)記. (類似于dagger中是@Named).

什么意思? 比如我們緩存接口有內(nèi)存和磁盤兩種實(shí)現(xiàn):

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class CacheInMemory

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class CacheInDisk

module中提供的時(shí)候用來標(biāo)記相應(yīng)的依賴:

@InstallIn(ApplicationComponent::class)
@Module
object CacheModule {

    @CacheInMemory
    @Singleton
    @Provides
    fun getCacheInMemory(memoryImpl: CacheSourceMemoryImpl): CacheSource = memoryImpl
    
    @CacheInDisk
    @Singleton
    @Provides
    fun getCacheInDisk(diskImpl: CacheSourceDiskImpl): CacheSource = diskImpl
}

Android types

@AndroidEntryPoint

Dagger2中,對(duì)Activity和Fragment的注入依賴的使用比較麻煩粹排。

@Module
abstract class ActivityModule {

  @ActivityScope
  @ContributesAndroidInjector(modules = [MainActivityFragmentModule::class])
  internal abstract fun contributeMainActivity(): MainActivity

  @ActivityScope
  @ContributesAndroidInjector
  internal abstract fun contributeMovieDetailActivity(): MovieDetailActivity

  @ActivityScope
  @ContributesAndroidInjector
  internal abstract fun contributeTvDetailActivity(): TvDetailActivity

  @ActivityScope
  @ContributesAndroidInjector
  internal abstract fun contributePersonDetailActivity(): PersonDetailActivity
}

Hilt中就比較簡(jiǎn)單了,只需要@AndroidEntryPoint的注解涩澡。相當(dāng)于上面的@ContributesAndroidInjector顽耳。

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    //
    private val mJokesViewModel: JokesViewModel by viewModels()
     private val mBinding: ActivityMainBinding by viewBinding {
        ActivityMainBinding.inflate(layoutInflater)
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(mBinding.root)
        mJokesViewModel.jokes.observe(this, Observer {
                ........
        }

    }
}

我們不需要編寫AndroidInjection.inject(this)或擴(kuò)展DaggerAppCompatActivity類。

這里官方給了限定范圍:

  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

Hilt currently only supports activities that extend ComponentActivity and fragments that extend androidx library Fragment, not the (now deprecated) Fragment in the Android platform.

Hilt目前不直接支持 content providers.

@EntryPoint

Hilt支持最常用的Android組件, 對(duì)于默認(rèn)不支持的類型, 如果要做字段注入, 需要用@EntryPoint.

這里只是限制了字段注入的情況, 對(duì)于自定義類型我們一般習(xí)慣于用構(gòu)造注入。

必須與@InstallIn搭配使用射富,將interface標(biāo)記為入口點(diǎn)膝迎,這樣就可以使用Hilt容器提供的依賴對(duì)象們.

如果要content provider使用Hilt

class ExampleContentProvider : ContentProvider() {

  @EntryPoint
  @InstallIn(ApplicationComponent::class)
  interface ExampleContentProviderEntryPoint {
    fun analyticsService(): AnalyticsService
  }

  ...
}

要訪問@EntryPoint,使用靜態(tài)方法 EntryPointAccessors

class ExampleContentProvider: ContentProvider() {
    ...

  override fun query(...): Cursor {
    val appContext = context?.applicationContext ?: throw IllegalStateException()
    val hiltEntryPoint =
      EntryPointAccessors.fromApplication(appContext, ExampleContentProviderEntryPoint::class.java)

    val analyticsService = hiltEntryPoint.analyticsService()
    ...
  }
}

appContext參數(shù)要與@InstallIn(ApplicationComponent::class)保持一致胰耗。

@EntryPoint除了解決上述字段注入的 問題限次,還有什么場(chǎng)景可以發(fā)揮用處?

生命周期匹配

我們利用FragmentFactoryActivityFragment之間用構(gòu)造函數(shù)傳遞數(shù)據(jù) :

class ContainerActivity : AppCompatActivity() {
    
    private var fragmentDataTest = FragmentDataTest()
    private val mBinding: ActivityContainerBinding by viewBinding {
        ActivityContainerBinding.inflate(layoutInflater)
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        supportFragmentManager.fragmentFactory = EntryPointFragmentFactory(fragmentDataTest)
        super.onCreate(savedInstanceState)
        setContentView(mBinding.root)
        setSupportActionBar(mBinding.toolbar)
    }
}

看上述代碼柴灯,在沒有用Hilt之前fragmentFactory的設(shè)置應(yīng)該是在 super.onCreate()之前卖漫,但是如果用Hilt就不能這么寫了,因?yàn)樵?/p>

之前Hilt Application中已經(jīng)說過赠群,Hilt是在super.onCreate()中進(jìn)行依賴注入的羊始,在Hilt_ContainerActivity類中:

  @CallSuper
  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    inject();
    super.onCreate(savedInstanceState);
  }

<u>Injection happens in super.onCreate().</u>

所以,如果我們要在ContainerActivity中使用FragmentFactory就該在super.onCreate()之后查描,那么問題來了...我們知道FragmentFactory 負(fù)責(zé)在 Activity 和 parent Fragment 初始化 Fragment突委,應(yīng)該在 super.onCreate() 之前關(guān)聯(lián) FragmentFactory 和 FragmentManager設(shè)置。如果在使用Hilt注入之后還是放在編譯會(huì)報(bào)錯(cuò):

UninitializedPropertyAccessException: lateinit property mFragmentFactory has not been initialized

所以我們將FragmentManager綁定FragmentFactory的動(dòng)作放在super.onCreate()之后:

@AndroidEntryPoint
class ContainerActivity : AppCompatActivity() {

    @Inject lateinit var mFragmentFactory: EntryPointFragmentFactory

    private val mBinding: ActivityContainerBinding by viewBinding {
        ActivityContainerBinding.inflate(layoutInflater)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        supportFragmentManager.fragmentFactory = mFragmentFactory
        setContentView(mBinding.root)
        mFragmentFactory.fragmentDataTest.setData("xxx")
    }
}

這樣就可以了冬三,但是要注意了:

<u>如果上面的ContainerActivity被意外終止而觸發(fā)重建的話是會(huì)報(bào)錯(cuò)的 :</u>

 java.lang.RuntimeException: Unable to start activity ComponentInfo{tt.reducto.daggerhiltsample/tt.reducto.daggerhiltsample.ui.entry.ContainerActivity}: androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment tt.reducto.daggerhiltsample.ui.entry.EntryPointFragment: could not find Fragment constructor
 ...
Caused by: androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment tt.reducto.daggerhiltsample.ui.entry.EntryPointFragment: could not find Fragment constructor
  

可以定位 Hilt_ContainerActivity中的super.onCreate(savedInstanceState);這里就涉及到FragmentManager的狀態(tài)保存與恢復(fù)

Fragment依附于Activity匀油,而Fragment的狀態(tài)保存與恢復(fù)機(jī)制也是由Activity的相關(guān)方法觸發(fā)。Activity的方法onSaveInstanceState(Bundle outState)的參數(shù)outState是系統(tǒng)在狀態(tài)需要保存時(shí)用來提供存放持久化狀態(tài)的容器勾笆,當(dāng)系統(tǒng)觸發(fā)狀態(tài)保存時(shí)敌蚜,Activity下的Fragment的所有狀態(tài)便通過mFragments的saveAllState方法保存在了 FRAGMENTS_TAG 鍵中,在Activity重建 的 時(shí)候通過mFragments.restoreAllState入口將狀態(tài)恢復(fù)

在此期間Fragment的都會(huì)交由FragmentManager管理匠襟,包括我們需要注意的如何新建一個(gè)Fragment對(duì)象:

Fragment.instantiate(…)方法會(huì)根據(jù)所給的class name加載對(duì)應(yīng)的Class類钝侠,調(diào)用clazz.newInstance()新建一個(gè)全新的Fragment對(duì)象:

public static Fragment instantiate(Context context, String fname, @Nullable Bundle args) {
    ...
    Fragment f = (Fragment)clazz.newInstance();
    if (args != null) {
        args.setClassLoader(f.getClass().getClassLoader());
        f.mArguments = args;
    }
    ...
}

綜上,Activity重建后無法利用FragmentFactory重新創(chuàng)建Fragment酸舍,所以官方FragmentFactory文檔才有這么一句話:

  • Before the system restores the Fragment, if the Fragment is being recreated after a configuration change or the app’s process restart.

了解了FragmentManager綁定FragmentFactory的動(dòng)作在super.onCreate()之前執(zhí)行的必要性后帅韧,我們?cè)賮砝肏ilt提供的特性解決聲明周期不匹配的問題

@EntryPoint
@InstallIn(ActivityComponent::class)
interface ContainerActivityEntryPoint {
    fun getFragmentManager(): FragmentManager
    fun getFragmentFactory(): EntryPointFragmentFactory
}

我們利用@EntryPointContainerActivityEntryPoint對(duì)象中獲取FragmentManager和EntryPointFragmentFactory的引用:

@AndroidEntryPoint
class ContainerActivity : AppCompatActivity() {

    private val mBinding: ActivityContainerBinding by viewBinding {
        ActivityContainerBinding.inflate(layoutInflater)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        val entryPoint  = EntryPointAccessors.fromActivity(this,ContainerActivityEntryPoint::class.java)
        val mFragmentFactory = entryPoint.getFragmentFactory()
        entryPoint.getFragmentManager().fragmentFactory = mFragmentFactory
        super.onCreate(savedInstanceState)
        setContentView(mBinding.root)
        mFragmentFactory.fragmentDataTest.setData("xxxxxxxxxxx")
    }
        ......
}

從靜態(tài)類EntryPointAccessors中獲取定義的實(shí)例,有點(diǎn)SOLID中接口隔離原則的意思啃勉。

再次模擬Activity重建狀態(tài)忽舟,一切正常。

ViewModel

之前Dagger注入ViewModel時(shí)比較麻煩淮阐,在構(gòu)造函數(shù)中創(chuàng)建帶有參數(shù)的ViewModel實(shí)例叮阅,每個(gè)ViewModel必須實(shí)現(xiàn)一個(gè)全局或每個(gè)ViewModelFactory,并實(shí)現(xiàn)ViewModelModule來綁定ViewModel泣特。

@Module
internal abstract class ViewModelModule {

  @Binds
  @IntoMap
  @ViewModelKey(MainActivityViewModel::class)
  internal abstract fun bindMainActivityViewModels(mainActivityViewModel: MainActivityViewModel): ViewModel
    ......
  }

Hilt更簡(jiǎn)單:

class JokesViewModel @ViewModelInject constructor(
    private val jokesRepository: JokesRepository,
    private val netWorkUtils: NetWorkUtils,
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {
        ........
}

使用@ViewModelInject即可浩姥,JokesRepositoryNetWorkUtils都是由Hilt注入的状您。

Hilt將在后臺(tái)生成相應(yīng)的工廠類和東西勒叠。

這里有個(gè)@Assisted需要注意下:

因?yàn)樵谶@之前ViewModel中注入SavedStateHandle是比較麻煩的兜挨,由于@AssistedInject.Factory修飾接口再通過@AssistedInject注入ViewModel,最后還要通過@AssistedModule`中添加.....太太太麻煩了

看下Hilt@Assisted描述:

/**
 * Marks a parameter in a {@link androidx.hilt.lifecycle.ViewModelInject}-annotated constructor
 * or a {@link androidx.hilt.work.WorkerInject}-annotated constructor to be assisted
 * injected at runtime via a factory.
 */
// TODO(danysantiago): Remove and replace with dagger.assisted.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Assisted {
}

意思是Worker通過@WorkerInject構(gòu)造函數(shù)注入時(shí)要通過@Assisted修飾ContextWorkerParameters

類似:

class ExampleWorker @WorkerInject constructor(
  @Assisted appContext: Context,
  @Assisted workerParams: WorkerParameters,
  workerDependency: WorkerDependency
) : Worker(appContext, workerParams) { ... }

簡(jiǎn)單例子

利用Hilt寫個(gè)超簡(jiǎn)單的請(qǐng)求列表的小例子:Github

image

總結(jié)

  • 不用手動(dòng)創(chuàng)建Component.
  • 不用手動(dòng)調(diào)用inject()進(jìn)行字段注入.
  • 不用在Application中保存component.
  • 提供一些Scope管理他們的生命周期眯分,只能在對(duì)應(yīng)的范圍內(nèi)進(jìn)行使用拌汇。
  • 提供了一些默認(rèn)依賴, 比如Context.

以上就是Dagger Hilt簡(jiǎn)單上手,

目前Hilt還處于alpha狀態(tài)弊决,依賴kapt噪舀,等KSP成熟之后預(yù)計(jì)效率會(huì)有進(jìn)一步提升。

當(dāng)然koin玩起來更舒心飘诗。

參考

https://developer.android.com/training/dependency-injection/hilt-android#not-supported

https://developer.android.com/training/dependency-injection/hilt-android

http://joebirch.co/android/exploring-dagger-hilt-application-level-code-generation/

https://www.techyourchance.com/dagger-hilt-entry-point/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末与倡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子疚察,更是在濱河造成了極大的恐慌蒸走,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件貌嫡,死亡現(xiàn)場(chǎng)離奇詭異比驻,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)岛抄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門别惦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人夫椭,你說我怎么就攤上這事掸掸。” “怎么了蹭秋?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵扰付,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我仁讨,道長(zhǎng)羽莺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任洞豁,我火速辦了婚禮盐固,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丈挟。我一直安慰自己刁卜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布曙咽。 她就那樣靜靜地躺著蛔趴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪例朱。 梳的紋絲不亂的頭發(fā)上夺脾,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天之拨,我揣著相機(jī)與錄音茉继,去河邊找鬼咧叭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛烁竭,可吹牛的內(nèi)容都是我干的菲茬。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼派撕,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼婉弹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起终吼,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤镀赌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后际跪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體商佛,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年姆打,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了良姆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡幔戏,死狀恐怖玛追,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情闲延,我是刑警寧澤痊剖,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站垒玲,受9級(jí)特大地震影響陆馁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜侍匙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一氮惯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧想暗,春花似錦妇汗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至储狭,卻和暖如春互婿,著一層夾襖步出監(jiān)牢的瞬間捣郊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工慈参, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呛牲,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓驮配,卻偏偏與公主長(zhǎng)得像娘扩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子壮锻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344