Hilt ile bağımlı yerleştirme

Hilt, Android için projenizde manuel bağımlılık eklemenin ortak yolunu azaltan bir bağımlılık yerleştirme kitaplığıdır. Manuel bağımlılık ekleme yapmak için her sınıfı ve bağımlılıklarını elle oluşturmanız ve bağımlılıkları yeniden kullanmak ve yönetmek için container'ları kullanmanız gerekir.

Hilt, projenizdeki her Android sınıfı için container'lar sağlayıp bunların yaşam döngülerini otomatik olarak yöneterek uygulamanızda DI kullanımının standart bir yolunu sunar. Hilt, popüler DI kitaplığı Dagger'ın üzerine kurulmuştur. Böylece, Dagger'ın sağladığı derleme zamanı doğruluğu, çalışma zamanı performansı, ölçeklenebilirlik ve Android Studio desteğinden yararlanabilir. Daha fazla bilgi için Hilt ve Dagger'a bakın.

Bu kılavuzda, Hilt'in temel kavramları ve oluşturduğu kapsayıcılar açıklanmaktadır. Ayrıca, Hilt'i kullanmak için mevcut bir uygulamanın nasıl önyükleneceğine dair bir tanıtım da bulunuyor.

Bağımlılık ekleme

İlk olarak hilt-android-gradle-plugin eklentisini projenizin kök build.gradle dosyasına ekleyin:

Eski

plugins {
  ...
  id 'com.google.dagger.hilt.android' version '2.44' apply false
}

Kotlin

plugins {
  ...
  id("com.google.dagger.hilt.android") version "2.44" apply false
}

Ardından Gradle eklentisini uygulayın ve app/build.gradle dosyanıza şu bağımlılıkları ekleyin:

Eski

...
plugins {
  id 'kotlin-kapt'
  id 'com.google.dagger.hilt.android'
}

android {
  ...
}

dependencies {
  implementation "com.google.dagger:hilt-android:2.44"
  kapt "com.google.dagger:hilt-compiler:2.44"
}

// Allow references to generated code
kapt {
  correctErrorTypes true
}

Kotlin

plugins {
  id("kotlin-kapt")
  id("com.google.dagger.hilt.android")
}

android {
  ...
}

dependencies {
  implementation("com.google.dagger:hilt-android:2.44")
  kapt("com.google.dagger:hilt-android-compiler:2.44")
}

// Allow references to generated code
kapt {
  correctErrorTypes = true
}

Hilt, Java 8 özelliklerini kullanır. Projenizde Java 8'i etkinleştirmek için app/build.gradle dosyasına şunu ekleyin:

Eski

android {
  ...
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

Kotlin

android {
  ...
  compileOptions {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
  }
}

Hilt uygulama sınıfı

Hilt kullanan tüm uygulamalar, @HiltAndroidApp ek açıklaması olan bir Application sınıfı içermelidir.

@HiltAndroidApp, Hilt'in kod oluşturma işlemini tetikler. Bu kod, uygulamanız için uygulama düzeyinde bağımlılık kapsayıcısı görevi gören bir temel sınıf içerir.

Kotlin

@HiltAndroidApp
class ExampleApplication : Application() { ... }

Java

@HiltAndroidApp
public class ExampleApplication extends Application { ... }

Oluşturulan bu Hilt bileşeni, Application nesnesinin yaşam döngüsüne eklenir ve buna bağımlılıklar sağlar. Ayrıca, uygulamanın üst bileşenidir. Yani diğer bileşenler, sağladığı bağımlılıklara erişebilir.

Android sınıflarına bağımlılık ekleme

Hilt, Application sınıfınızda ayarlandıktan ve uygulama düzeyinde bir bileşen kullanıma sunulduktan sonra, Hilt, @AndroidEntryPoint ek açıklamasına sahip diğer Android sınıflarına bağımlılıklar sağlayabilir:

Kotlin

@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() { ... }

Java

@AndroidEntryPoint
public class ExampleActivity extends AppCompatActivity { ... }

Hilt, şu anda aşağıdaki Android sınıflarını desteklemektedir:

  • Application (@HiltAndroidApp kullanarak)
  • ViewModel (@HiltViewModel kullanarak)
  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

Bir Android sınıfına @AndroidEntryPoint ile ek açıklama eklerseniz bağımlı olan Android sınıflarına da not eklemeniz gerekir. Örneğin, bir parçaya ek açıklama eklerseniz bu parçayı kullandığınız tüm etkinliklere de ek açıklama eklemeniz gerekir.

@AndroidEntryPoint, projenizdeki her Android sınıfı için ayrı bir Hilt bileşeni oluşturur. Bu bileşenler, Bileşen hiyerarşisi bölümünde açıklandığı gibi ilgili üst sınıflarından bağımlılık alabilir.

Bir bileşenden bağımlılık elde etmek üzere alan yerleştirme işlemi gerçekleştirmek için @Inject ek açıklamasını kullanın:

Kotlin

@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {

  @Inject lateinit var analytics: AnalyticsAdapter
  ...
}

Java

@AndroidEntryPoint
public class ExampleActivity extends AppCompatActivity {

  @Inject
  AnalyticsAdapter analytics;
  ...
}

Hilt'in eklediği sınıflar, yerleştirme tekniğini de kullanan başka temel sınıflara sahip olabilir. Bu sınıflar soyutlarsa @AndroidEntryPoint ek açıklamasına ihtiyaç duymazlar.

Bir Android sınıfının hangi yaşam döngüsü geri çağırmasının yerleştirildiği hakkında daha fazla bilgi edinmek için Bileşen kullanım ömrü sayfasını inceleyin.

Hilt bağlamalarını tanımlama

Hilt'in, alan yerleştirme işlemi gerçekleştirmek için ilgili bileşenden gerekli bağımlılık örneklerini nasıl sağlayacağını bilmesi gerekir. Bağlama, bir türün örneklerini bağımlılık olarak sağlamak için gerekli bilgileri içerir.

Hilt'e bağlama bilgilerini sağlamanın bir yolu oluşturucu yerleştirmedir. Hilt'e, söz konusu sınıfın örneklerini nasıl sağlayacağını bildirmek için bir sınıfın oluşturucusunda @Inject ek açıklamasını kullanın:

Kotlin

class AnalyticsAdapter @Inject constructor(
  private val service: AnalyticsService
) { ... }

Java

public class AnalyticsAdapter {

  private final AnalyticsService service;

  @Inject
  AnalyticsAdapter(AnalyticsService service) {
    this.service = service;
  }
  ...
}

Bir sınıfın ek açıklamalı oluşturucusunun parametreleri, söz konusu sınıfın bağımlılıklarıdır. Örnekte AnalyticsAdapter, bir bağımlılık olarak AnalyticsService içermektedir. Bu nedenle, Hilt'in AnalyticsService örneklerini nasıl sağlayacağını da bilmesi gerekir.

Hilt modülleri

Bazen bir tür, kurucu tarafından yerleştirilemez. Bu durum farklı nedenlerle ortaya çıkabilir. Örneğin, bir arayüze oluşturucu ekleme yapamazsınız. Ayrıca, harici kitaplıktaki bir sınıf gibi sahibi olmadığınız bir türü de kurucu olarak ekleyemezsiniz. Bu gibi durumlarda Hilt modüllerini kullanarak Hilt'e bağlayıcı bilgiler sağlayabilirsiniz.

Hilt modülü, @Module ek açıklamasına sahip bir sınıftır. Dagger modülü gibi, Hilt'e de belirli türlerin örneklerini nasıl sağlayacağını bildirir. Dagger modüllerinin aksine, Hilt'e her modülün hangi Android sınıfının kullanılacağını veya yükleneceğini belirtmek için Hilt modüllerine @InstallIn ek açıklaması eklemeniz gerekir.

Hilt modüllerinde sağladığınız bağımlılıklar, Hilt modülünü yüklediğiniz Android sınıfıyla ilişkilendirilmiş, oluşturulmuş tüm bileşenlerde kullanılabilir.

Arayüz örneklerini @Binds ile ekleyin

AnalyticsService örneğini düşünün. AnalyticsService bir arayüzse bunu oluşturucu yerleştiremezsiniz. Bunun yerine, Hilt modülü içinde @Binds ile açıklama eklenen bir soyut işlev oluşturarak Hilt'e bağlama bilgilerini sağlayın.

@Binds ek açıklaması, Hilt'e bir arayüz örneği sağlaması gerektiğinde hangi uygulamanın kullanılacağını bildirir.

Ek açıklamalı işlev, Hilt'e aşağıdaki bilgileri sağlar:

  • İşlev dönüş türü, Hilt'e, işlevin hangi arayüzün örneklerini sağladığını bildirir.
  • İşlev parametresi, Hilt'e hangi uygulamayı sağlayacağını bildirir.

Kotlin

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
}

Java

public interface AnalyticsService {
  void analyticsMethods();
}

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

@Module
@InstallIn(ActivityComponent.class)
public abstract class AnalyticsModule {

  @Binds
  public abstract AnalyticsService bindAnalyticsService(
    AnalyticsServiceImpl analyticsServiceImpl
  );
}

Hilt modülüne AnalyticsModule ek @InstallIn(ActivityComponent.class) ifadesi eklenmiş çünkü Hilt'in bu bağımlılığı ExampleActivity etiketine yerleştirmesini istiyorsunuz. Bu ek açıklama, AnalyticsModule içindeki tüm bağımlılıkların, uygulamanın tüm etkinliklerinde kullanılabileceği anlamına gelir.

@Provides ile örnek yerleştirme

Bir tür kurucu ekleyemeyeceğiniz tek durum arayüz değildir. Sınıfın sahibi siz değilseniz harici bir kitaplıktan (Retrofit, OkHttpClient veya Oda veritabanları) geldiği ya da örneklerin derleyici kalıbı ile oluşturulması gerekiyorsa oluşturucu ekleme işlemi de yapılamaz.

Bir önceki örneği inceleyelim. AnalyticsService sınıfına doğrudan sahip değilseniz bir Hilt modülü içinde işlev oluşturup bu işleve @Provides ile not ekleyerek Hilt'e bu tür örnekleri nasıl sağlayacağını bildirebilirsiniz.

Ek açıklamalı işlev, Hilt'e aşağıdaki bilgileri sağlar:

  • İşlev dönüş türü, Hilt'e, işlevin hangi tür örneklerini sağladığını bildirir.
  • İşlev parametreleri, Hilt'e ilgili türün bağımlılıklarını bildirir.
  • İşlev gövdesi, Hilt'e karşılık gelen türün bir örneğini nasıl sağlayacağını bildirir. Hilt, bu tür bir örnek sağlaması gerektiğinde işlev gövdesini yürütür.

Kotlin

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

  @Provides
  fun provideAnalyticsService(
    // Potential dependencies of this type
  ): AnalyticsService {
      return Retrofit.Builder()
               .baseUrl("https://example.com")
               .build()
               .create(AnalyticsService::class.java)
  }
}

Java

@Module
@InstallIn(ActivityComponent.class)
public class AnalyticsModule {

  @Provides
  public static AnalyticsService provideAnalyticsService(
    // Potential dependencies of this type
  ) {
      return new Retrofit.Builder()
               .baseUrl("https://example.com")
               .build()
               .create(AnalyticsService.class);
  }
}

Aynı tür için birden çok bağlama sağlayın

Bağımlılıklarla aynı türün farklı uygulamalarını sağlaması için Hilt'e ihtiyaç duyduğunuz durumlarda, Hilt'e birden çok bağlama sağlamanız gerekir. Niteleyicilerle aynı tür için birden fazla bağlama tanımlayabilirsiniz.

Niteleyici, bir tür için tanımlanmış birden fazla bağlama olduğunda belirli bir bağlamayı tanımlamak üzere kullandığınız ek açıklamadır.

Örneği düşünün. AnalyticsService çağrılarına müdahale etmeniz gerekirse bir arayıcı ile OkHttpClient nesnesi kullanabilirsiniz. Diğer hizmetler için aramalara farklı bir şekilde müdahale etmeniz gerekebilir. Bu durumda, Hilt'e OkHttpClient öğesinin iki farklı uygulamasını nasıl sağlayacağını bildirmeniz gerekir.

Öncelikle, @Binds veya @Provides yöntemlerine ek açıklama eklemek için kullanacağınız niteleyicileri tanımlayın:

Kotlin

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

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

Java

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
private @interface AuthInterceptorOkHttpClient {}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
private @interface OtherInterceptorOkHttpClient {}

Ardından, Hilt'in her niteleyiciye karşılık gelen türün bir örneğini nasıl sağlayacağını bilmesi gerekir. Bu durumda, @Provides ile bir Hilt modülü kullanabilirsiniz. Her iki yöntem de aynı döndürme türüne sahiptir ancak niteleyiciler bunları iki farklı bağlama olarak etiketler:

Kotlin

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

  @AuthInterceptorOkHttpClient
  @Provides
  fun provideAuthInterceptorOkHttpClient(
    authInterceptor: AuthInterceptor
  ): OkHttpClient {
      return OkHttpClient.Builder()
               .addInterceptor(authInterceptor)
               .build()
  }

  @OtherInterceptorOkHttpClient
  @Provides
  fun provideOtherInterceptorOkHttpClient(
    otherInterceptor: OtherInterceptor
  ): OkHttpClient {
      return OkHttpClient.Builder()
               .addInterceptor(otherInterceptor)
               .build()
  }
}

Java

@Module
@InstallIn(ActivityComponent.class)
public class NetworkModule {

  @AuthInterceptorOkHttpClient
  @Provides
  public static OkHttpClient provideAuthInterceptorOkHttpClient(
    AuthInterceptor authInterceptor
  ) {
      return new OkHttpClient.Builder()
                   .addInterceptor(authInterceptor)
                   .build();
  }

  @OtherInterceptorOkHttpClient
  @Provides
  public static OkHttpClient provideOtherInterceptorOkHttpClient(
    OtherInterceptor otherInterceptor
  ) {
      return new OkHttpClient.Builder()
                   .addInterceptor(otherInterceptor)
                   .build();
  }
}

Alana veya parametreye ilgili niteleyiciyle not ekleyerek ihtiyacınız olan belirli bir türü ekleyebilirsiniz:

Kotlin

// As a dependency of another class.
@Module
@InstallIn(ActivityComponent::class)
object AnalyticsModule {

  @Provides
  fun provideAnalyticsService(
    @AuthInterceptorOkHttpClient okHttpClient: OkHttpClient
  ): AnalyticsService {
      return Retrofit.Builder()
               .baseUrl("https://example.com")
               .client(okHttpClient)
               .build()
               .create(AnalyticsService::class.java)
  }
}

// As a dependency of a constructor-injected class.
class ExampleServiceImpl @Inject constructor(
  @AuthInterceptorOkHttpClient private val okHttpClient: OkHttpClient
) : ...

// At field injection.
@AndroidEntryPoint
class ExampleActivity: AppCompatActivity() {

  @AuthInterceptorOkHttpClient
  @Inject lateinit var okHttpClient: OkHttpClient
}

Java

// As a dependency of another class.
@Module
@InstallIn(ActivityComponent.class)
public class AnalyticsModule {

  @Provides
  public static AnalyticsService provideAnalyticsService(
    @AuthInterceptorOkHttpClient OkHttpClient okHttpClient
  ) {
      return new Retrofit.Builder()
                  .baseUrl("https://example.com")
                  .client(okHttpClient)
                  .build()
                  .create(AnalyticsService.class);
  }
}

// As a dependency of a constructor-injected class.
public class ExampleServiceImpl ... {

  private final OkHttpClient okHttpClient;

  @Inject
  ExampleServiceImpl(@AuthInterceptorOkHttpClient OkHttpClient okHttpClient) {
    this.okHttpClient = okHttpClient;
  }
}

// At field injection.
@AndroidEntryPoint
public class ExampleActivity extends AppCompatActivity {

  @AuthInterceptorOkHttpClient
  @Inject
  OkHttpClient okHttpClient;
  ...
}

En iyi uygulama olarak, bir türe niteleyici eklerseniz bu bağımlılığı sağlamanın mümkün olan tüm yollarına niteleyici ekleyin. Tabanın veya ortak uygulamanın bir niteleyici olmadan bırakılması hataya açıktır ve Hilt'in yanlış bağımlılığı yerleştirmesine neden olabilir.

Hilt'te önceden tanımlanmış niteleyiciler

Hilt, önceden tanımlanmış bazı niteleyiciler sağlar. Örneğin, Context sınıfına uygulama veya etkinlikten ihtiyaç duyabileceğiniz için Hilt, @ApplicationContext ve @ActivityContext niteleyicilerini sağlar.

Örnekteki AnalyticsAdapter sınıfının etkinliğin bağlamına ihtiyaç duyduğunu varsayalım. Aşağıdaki kod, etkinlik bağlamının AnalyticsAdapter öğesine nasıl sağlanacağını gösterir:

Kotlin

class AnalyticsAdapter @Inject constructor(
    @ActivityContext private val context: Context,
    private val service: AnalyticsService
) { ... }

Java

public class AnalyticsAdapter {

  private final Context context;
  private final AnalyticsService service;

  @Inject
  AnalyticsAdapter(
    @ActivityContext Context context,
    AnalyticsService service
  ) {
    this.context = context;
    this.service = service;
  }
}

Hilt'te kullanılabilen diğer önceden tanımlanmış bağlamalar için Bileşen varsayılan bağlamaları bölümüne bakın.

Android sınıfları için oluşturulan bileşenler

Alan yerleştirme işlemi gerçekleştirebileceğiniz her Android sınıfı için @InstallIn ek açıklamasında başvurabileceğiniz ilişkili bir Hilt bileşeni vardır. Her Hilt bileşeni, bağlamalarını karşılık gelen Android sınıfına eklemekten sorumludur.

Önceki örnekler, Hilt modüllerinde ActivityComponent kullanımını göstermektedir.

Hilt aşağıdaki bileşenleri sağlar:

Sap bileşeni Ekleyici:
SingletonComponent Application
ActivityRetainedComponent Yok
ViewModelComponent ViewModel
ActivityComponent Activity
FragmentComponent Fragment
ViewComponent View
ViewWithFragmentComponent View, @WithFragmentBindings ile notlandırıldı
ServiceComponent Service

Bileşen kullanım ömrü

Hilt, ilgili Android sınıflarının yaşam döngüsünü izleyerek oluşturulan bileşen sınıflarının örneklerini otomatik olarak oluşturur ve kaldırır.

Oluşturulan bileşen Oluşturulma zamanı Yıkıldığı tarih:
SingletonComponent Application#onCreate() Application kaldırıldı
ActivityRetainedComponent Activity#onCreate() Activity#onDestroy()
ViewModelComponent ViewModel oluşturuldu ViewModel kaldırıldı
ActivityComponent Activity#onCreate() Activity#onDestroy()
FragmentComponent Fragment#onAttach() Fragment#onDestroy()
ViewComponent View#super() View kaldırıldı
ViewWithFragmentComponent View#super() View kaldırıldı
ServiceComponent Service#onCreate() Service#onDestroy()

Bileşen kapsamları

Varsayılan olarak Hilt'teki tüm bağlamaların kapsamı kaldırılır. Bu, uygulamanızın her bağlantı isteğinde bulunduğunda Hilt'in gerekli türde yeni bir örnek oluşturduğu anlamına gelir.

Bu örnekte, Hilt başka bir türe bağımlılık olarak veya ExampleActivity'da olduğu gibi alan yerleştirme yoluyla AnalyticsAdapter her sağladığında, Hilt yeni bir AnalyticsAdapter örneği sağlar.

Bununla birlikte, Hilt, bağlamanın belirli bir bileşene ayarlanmasına da olanak tanır. Hilt, bağlamanın kapsama dahil olduğu bileşenin her örneği için yalnızca bir kez kapsamlı bağlama oluşturur ve bu bağlamaya yönelik tüm istekler aynı örneği paylaşır.

Aşağıdaki tabloda, oluşturulan her bileşen için kapsam ek açıklamaları listelenmiştir:

Android sınıfı Oluşturulan bileşen Kapsam
Application SingletonComponent @Singleton
Activity ActivityRetainedComponent @ActivityRetainedScoped
ViewModel ViewModelComponent @ViewModelScoped
Activity ActivityComponent @ActivityScoped
Fragment FragmentComponent @FragmentScoped
View ViewComponent @ViewScoped
View, @WithFragmentBindings ile notlandırıldı ViewWithFragmentComponent @ViewScoped
Service ServiceComponent @ServiceScoped

Bu örnekte, @ActivityScoped kullanarak ActivityComponent kapsamını AnalyticsAdapter kapsamına alırsanız Hilt, ilgili etkinliğin süresi boyunca aynı AnalyticsAdapter örneğini sağlar:

Kotlin

@ActivityScoped
class AnalyticsAdapter @Inject constructor(
  private val service: AnalyticsService
) { ... }

Java

@ActivityScoped
public class AnalyticsAdapter {

  private final AnalyticsService service;

  @Inject
  AnalyticsAdapter(AnalyticsService service) {
    this.service = service;
  }
  ...
}

AnalyticsService işlevinin, aynı örneğin yalnızca ExampleActivity ürününde değil, uygulamanın herhangi bir yerinde her zaman kullanılmasını gerektiren bir dahili duruma sahip olduğunu varsayalım. Bu durumda, AnalyticsService kapsamının SingletonComponent içine alınması uygundur. Sonuç olarak, bileşenin AnalyticsService örneği sağlaması gerektiğinde her seferinde aynı örneği sağlar.

Aşağıdaki örnekte, Hilt modülündeki bir bileşene bağlamanın kapsamının nasıl belirleneceği gösterilmektedir. Bir bağlamanın kapsamı, yüklendiği bileşenin kapsamıyla eşleşmelidir. Dolayısıyla bu örnekte, ActivityComponent yerine SingletonComponent uygulamasına AnalyticsService yüklemeniz gerekir:

Kotlin

// If AnalyticsService is an interface.
@Module
@InstallIn(SingletonComponent::class)
abstract class AnalyticsModule {

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

// If you don't own AnalyticsService.
@Module
@InstallIn(SingletonComponent::class)
object AnalyticsModule {

  @Singleton
  @Provides
  fun provideAnalyticsService(): AnalyticsService {
      return Retrofit.Builder()
               .baseUrl("https://example.com")
               .build()
               .create(AnalyticsService::class.java)
  }
}

Java

// If AnalyticsService is an interface.
@Module
@InstallIn(SingletonComponent.class)
public abstract class AnalyticsModule {

  @Singleton
  @Binds
  public abstract AnalyticsService bindAnalyticsService(
    AnalyticsServiceImpl analyticsServiceImpl
  );
}

// If you don't own AnalyticsService.
@Module
@InstallIn(SingletonComponent.class)
public class AnalyticsModule {

  @Singleton
  @Provides
  public static AnalyticsService provideAnalyticsService() {
      return new Retrofit.Builder()
               .baseUrl("https://example.com")
               .build()
               .create(AnalyticsService.class);
  }
}

Hilt bileşen kapsamları hakkında daha fazla bilgi edinmek için Android ve Hilt'te Kapsam Oluşturma bölümüne bakın.

Bileşen hiyerarşisi

Bir bileşene modül yüklemek, ilgili bileşendeki veya bileşen hiyerarşisinde altında bulunan herhangi bir alt bileşendeki diğer bağlamaların bağımlılığı olarak bağlamalarına erişilmesine olanak tanır.

ViewWithFragmentComponent, FragmentComponent altındadır. FragmentComponent ve ViewComponent, ActivityComponent'ın altında yer alır. Etkinlik Bileşeni, ActivityRetainedComponent altındadır. ViewModelComponent, ActivityRetainedComponent altındadır. EventRetainedComponent ve ServiceComponent, SingletonComponent altında yer almaktadır.
Şekil 1. Hilt'in oluşturduğu bileşenlerin hiyerarşisi.

Bileşen varsayılan bağlamaları

Her Hilt bileşeni, Hilt'in kendi özel bağlamalarınıza bağımlılık olarak ekleyebileceği bir dizi varsayılan bağlamayla gelir. Bu bağlamaların herhangi bir belirli alt sınıfa değil, genel etkinliğe ve parça türlerine karşılık geldiğini unutmayın. Bunun nedeni, Hilt'in tüm etkinlikleri eklemek için tek bir aktivite bileşeni tanımı kullanmasıdır. Her etkinlikte bu bileşenin farklı bir örneği vardır.

Android bileşeni Varsayılan bağlamalar
SingletonComponent Application
ActivityRetainedComponent Application
ViewModelComponent SavedStateHandle
ActivityComponent Application, Activity
FragmentComponent Application, Activity, Fragment
ViewComponent Application, Activity, View
ViewWithFragmentComponent Application, Activity, Fragment, View
ServiceComponent Application, Service

Uygulama bağlamı bağlama, @ApplicationContext ile de kullanılabilir. Örnek:

Kotlin

class AnalyticsServiceImpl @Inject constructor(
  @ApplicationContext context: Context
) : AnalyticsService { ... }

// The Application binding is available without qualifiers.
class AnalyticsServiceImpl @Inject constructor(
  application: Application
) : AnalyticsService { ... }

Java

public class AnalyticsServiceImpl implements AnalyticsService {

  private final Context context;

  @Inject
  AnalyticsAdapter(@ApplicationContext Context context) {
    this.context = context;
  }
}

// The Application binding is available without qualifiers.
public class AnalyticsServiceImpl implements AnalyticsService {

  private final Application application;

  @Inject
  AnalyticsAdapter(Application application) {
    this.application = application;
  }
}

Etkinlik bağlamı bağlaması, @ActivityContext kullanılarak da yapılabilir. Örneğin:

Kotlin

class AnalyticsAdapter @Inject constructor(
  @ActivityContext context: Context
) { ... }

// The Activity binding is available without qualifiers.
class AnalyticsAdapter @Inject constructor(
  activity: FragmentActivity
) { ... }

Java

public class AnalyticsAdapter {

  private final Context context;

  @Inject
  AnalyticsAdapter(@ActivityContext Context context) {
    this.context = context;
  }
}

// The Activity binding is available without qualifiers.
public class AnalyticsAdapter {

  private final FragmentActivity activity;

  @Inject
  AnalyticsAdapter(FragmentActivity activity) {
    this.activity = activity;
  }
}

Hilt tarafından desteklenmeyen sınıflara bağımlılık ekleme

Hilt, en yaygın Android sınıfları için destek içerir. Ancak, Hilt'in desteklemediği sınıflarda alan yerleştirme işlemi gerçekleştirmeniz gerekebilir.

Böyle durumlarda, @EntryPoint notunu kullanarak bir giriş noktası oluşturabilirsiniz. Giriş noktası, Hilt tarafından yönetilen kod ile yönetilmeyen kod arasındaki sınırdır. Kodun, Hilt'in yönettiği nesne grafiğine ilk girdiği noktadır. Giriş noktaları, Hilt'in bağımlılık grafiğinde bağımlılık sağlamak için yönetemediği kodu kullanmasına olanak tanır.

Örneğin, Hilt, içerik sağlayıcıları doğrudan desteklemez. Bir içerik sağlayıcının bazı bağımlılıkları almak için Hilt'i kullanmasını istiyorsanız istediğiniz her bağlama türü için @EntryPoint ile açıklama eklenen bir arayüz tanımlamanız ve niteleyiciler eklemeniz gerekir. Ardından, giriş noktasının yükleneceği bileşeni belirtmek için @InstallIn öğesini aşağıdaki şekilde ekleyin:

Kotlin

class ExampleContentProvider : ContentProvider() {

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

  ...
}

Java

public class ExampleContentProvider extends ContentProvider {

  @EntryPoint
  @InstallIn(SingletonComponent.class)
  interface ExampleContentProviderEntryPoint {
    public AnalyticsService analyticsService();
  }
  ...
}

Bir giriş noktasına erişmek için EntryPointAccessors'den uygun statik yöntemi kullanın. Parametre, bileşen örneği veya bileşen tutucu olarak işlev gören @AndroidEntryPoint nesnesi olmalıdır. Parametre olarak ilettiğiniz bileşenin ve EntryPointAccessors statik yönteminin @EntryPoint arayüzündeki @InstallIn ek açıklamasındaki Android sınıfıyla eşleştiğinden emin olun:

Kotlin

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()
    ...
  }
}

Java

public class ExampleContentProvider extends ContentProvider {

  @Override
  public Cursor query(...) {
    Context appContext = getContext().getApplicationContext();
    ExampleContentProviderEntryPoint hiltEntryPoint =
      EntryPointAccessors.fromApplication(appContext, ExampleContentProviderEntryPoint.class);
    AnalyticsService analyticsService = hiltEntryPoint.analyticsService();
  }
}

Bu örnekte, giriş noktası SingletonComponent üzerinde yüklü olduğundan giriş noktasını almak için ApplicationContext kullanmanız gerekir. Almak istediğiniz bağlama ActivityComponent içinde olsaydı bunun yerine ActivityContext öğesini kullanırsınız.

Kaçak ve Hançer

Dagger bağımlılık ekleme kitaplığının üzerine kurulmuş olan Hilt, Dagger'ı bir Android uygulamasına eklemek için standart bir yol sağlar.

Dagger ile ilgili olarak, Hilt'in hedefleri aşağıdaki gibidir:

  • Android uygulamaları için Dagger ile ilgili altyapıyı basitleştirmek.
  • Kurulumu, okunabilirliği ve uygulamalar arasında kod paylaşımını kolaylaştırmak amacıyla standart bir bileşen ve kapsam grubu oluşturmak için kullanılır.
  • Test, hata ayıklama veya sürüm gibi çeşitli derleme türlerine farklı bağlamalar sağlamanın kolay bir yolunu sunmak amacıyla.

Android işletim sistemi kendi çerçeve sınıflarının çoğunu örneklendirdiğinden, bir Android uygulamasında Dagger'ı kullanmak için yüksek miktarda standart metin yazmanız gerekir. Hilt, bir Android uygulamasında Dagger kullanımında kullanılan standart kodu azaltmıştır. Hilt, aşağıdakileri otomatik olarak oluşturur ve sağlar:

  • Normalde elle oluşturmanız gerekeceği Android çerçeve sınıflarını Dagger ile entegre etmeye yönelik bileşenler.
  • Hilt'in otomatik olarak oluşturduğu bileşenlerle kullanılacak kapsam ek açıklamaları.
  • Application veya Activity gibi Android sınıflarını temsil etmek için önceden tanımlanmış bağlamalar.
  • @ApplicationContext ve @ActivityContext özelliklerini temsil edecek önceden tanımlanmış niteleyiciler.

Dagger ve Hilt kodu, aynı kod tabanında bir arada bulunabilir. Ancak çoğu durumda, Dagger'ı Android'deki tüm kullanımınızı yönetmek için Hilt'i kullanmanız en iyisidir. Dagger kullanan bir projeyi Hilt'e taşımak için taşıma rehberini ve Dagger uygulamanızı Hilt codelab'e taşıma başlıklı makaleleri inceleyin.

Ek kaynaklar

Hilt hakkında daha fazla bilgi edinmek için aşağıdaki ek kaynaklara bakın.

Numuneler

Codelab'ler

Bloglar