Hilt ile bağımlı yerleştirme

Hilt, Android için bir bağımlılık ekleme kitaplığıdır. Projenizde manuel bağımlılık ekleme işleminin ortak metin kodlarını azaltır. Manuel bağımlılık ekleme işlemi için her sınıfı ve bağımlılıklarını manuel olarak oluşturmanız, bağımlılıkları yeniden kullanmak ve yönetmek için de kapsayıcıları kullanmanız gerekir.

Hilt, projenizdeki her Android sınıfı için kapsayıcılar sağlayarak ve yaşam döngülerini otomatik olarak yöneterek uygulamanızda DI kullanmak için standart bir yol sunar. Hilt, Dagger'ın sağladığı derleme zamanı doğruluğu, çalışma zamanı performansı, ölçeklenebilirlik ve Android Studio desteği gibi avantajlardan yararlanmak için popüler DI kitaplığı Dagger'ın üzerine kurulmuştur. Daha fazla bilgi için Hilt ve Dagger başlıklı makaleyi inceleyin.

Bu kılavuzda, Hilt'in ve oluşturulan kapsayıcılarının temel kavramları açıklanmaktadır. Ayrıca, mevcut bir uygulamanın Hilt'i kullanacak şekilde nasıl başlatılacağıyla ilgili bir gösterim de içerir.

Bağımlılık ekleme

Öncelikle hilt-android-gradle-plugin eklentisini projenizin kök build.gradle dosyasına ekleyin:

Groovy

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

Kotlin

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

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

Groovy

...
plugins {
  id 'com.google.devtools.ksp'
  id 'com.google.dagger.hilt.android'
}

android {
  ...
}

dependencies {
  implementation "com.google.dagger:hilt-android:2.56.2"
  ksp "com.google.dagger:hilt-compiler:2.56.2"
}

Kotlin

plugins {
  id("com.google.devtools.ksp")
  id("com.google.dagger.hilt.android")
}

android {
  ...
}

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

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

Groovy

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 ile açıklama eklenmiş bir Application sınıfı içermelidir.

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

Kotlin

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

Java

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

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

Android sınıflarına bağımlılıkları yerleştirme

Hilt, Application sınıfınızda ayarlandıktan ve uygulama düzeyinde bir bileşen kullanılabilir hale geldikten sonra @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 kullanılarak)
  • ViewModel (@HiltViewModel kullanılarak)
  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

Bir Android sınıfına @AndroidEntryPoint ek açıklama uyguluyorsanız bu sınıfa bağlı Android sınıflarına da ek açıklama uygulamanız 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ıklar alabilir.

Bir bileşenden bağımlılıkları almak için alan yerleştirme işlemini gerçekleştirmek üzere @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 yerleştirdiği sınıfların, yerleştirme kullanan başka temel sınıfları olabilir. Bu sınıflar soyutsa @AndroidEntryPoint ek açıklamasına gerek yoktur.

Bir Android sınıfına hangi yaşam döngüsü geri çağırma işlevinin eklendiği hakkında daha fazla bilgi edinmek için Bileşen yaşam süreleri başlıklı makaleyi inceleyin.

Hilt bağlamalarını tanımlama

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

Hilt'e bağlama bilgileri sağlamanın bir yolu oluşturucu ekleme'dir. Hilt'e bu 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 açıklama eklenmiş oluşturucusunun parametreleri, söz konusu sınıfın bağımlılıklarıdır. Örnekte, AnalyticsAdapter öğesinin bağımlılığı AnalyticsService'dir. Bu nedenle, Hilt'in AnalyticsService örneklerini nasıl sağlayacağını da bilmesi gerekir.

Hilt modülleri

Bazen bir tür, oluşturucu aracılığıyla yerleştirilemez. Bunun birden fazla nedeni olabilir. Örneğin, bir arayüzü oluşturucu ile yerleştiremezsiniz. Ayrıca, harici bir kitaplıktaki sınıf gibi sahip olmadığınız bir türü oluşturucu olarak ekleyemezsiniz. Bu gibi durumlarda, Hilt modüllerini kullanarak Hilt'e bağlama bilgileri sağlayabilirsiniz.

Hilt modülü, @Module ile ek açıklama eklenmiş bir sınıftır. Dagger modülü gibi, belirli türlerin örneklerinin nasıl sağlanacağı konusunda Hilt'i bilgilendirir. Dagger modüllerinden farklı olarak, Hilt'e her modülün hangi Android sınıfında kullanılacağını veya yükleneceğini bildirmek için Hilt modüllerini @InstallIn ile açıklama 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şkili tüm oluşturulan bileşenlerde kullanılabilir.

@Binds ile arayüz örneklerini yerleştirme

AnalyticsService örneğini inceleyin. AnalyticsService bir arayüzse oluşturucu ekleme işlemi yapamazsınız. Bunun yerine, Hilt modülünde @Binds ile açıklama eklenmiş 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 uygulamayı kullanacağını bildirir.

Açıklama eklenmiş işlev, Hilt'e aşağıdaki bilgileri sağlar:

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

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'in bu bağımlılığı ExampleActivity içine yerleştirmesini istediğiniz için Hilt modülü AnalyticsModule, @InstallIn(ActivityComponent.class) ile açıklama eklenir. Bu açıklama, AnalyticsModule içindeki tüm bağımlılıkların uygulamanın tüm etkinliklerinde kullanılabildiği anlamına gelir.

@Provides ile örnekleri yerleştirme

Bir türe oluşturucu ekleyemediğiniz tek durum arayüzler değildir. Sınıf size ait değilse (Retrofit, OkHttpClient veya Room veritabanları gibi sınıflar harici bir kitaplıktan geliyorsa) veya örneklerin builder pattern ile oluşturulması gerekiyorsa oluşturucu ekleme de mümkün değildir.

Önceki örneği inceleyelim. AnalyticsService sınıfının doğrudan sahibi değilseniz Hilt modülünde bir işlev oluşturup bu işlevi @Provides ile açıklama ekleyerek Hilt'e bu türün örneklerini nasıl sağlayacağını söyleyebilirsiniz.

Açıklama eklenmiş işlev, Hilt'e aşağıdaki bilgileri sağlar:

  • İşlevin dönüş türü, Hilt'e işlevin hangi türde örnekler sağladığını bildirir.
  • İşlev parametreleri, Hilt'e ilgili türün bağımlılıklarını bildirir.
  • İşlev gövdesi, Hilt'e ilgili türün bir örneğini nasıl sağlayacağını söyler. Hilt, bu türün bir örneğini sağlaması gerektiğinde işlev gövdesini her seferinde 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 fazla bağlama sağlama

Hilt'in aynı türün farklı uygulamalarını bağımlılık olarak sağlaması gerektiği durumlarda Hilt'e birden fazla bağlama sağlamanız gerekir. Aynı tür için nitelendiricilerle birden fazla bağlama tanımlayabilirsiniz.

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

Örneği inceleyin. AnalyticsService'ya yapılan aramaları engellemeniz gerekiyorsa interceptor içeren bir OkHttpClient nesnesi kullanabilirsiniz. Diğer hizmetler için aramaları farklı bir şekilde engellemeniz gerekebilir. Bu durumda, Hilt'e OkHttpClient için iki farklı uygulamanın nasıl sağlanacağını söylemeniz gerekir.

Öncelikle @Binds veya @Provides yöntemlerini 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öntemin de dönüş türü aynıdır 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();
  }
}

Alanı veya parametreyi ilgili niteleyiciyle açıklama ekleyerek ihtiyacınız olan belirli 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 ekliyorsanız bu bağımlılığı sağlamanın olası tüm yollarına niteleyiciler ekleyin. Temel veya ortak uygulamayı niteleyici olmadan bırakmak hataya açık bir durumdur 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, uygulamadan veya etkinlikten Context sınıfına ihtiyacınız olabileceğinden Hilt, @ApplicationContext ve @ActivityContext niteleyicilerini sağlar.

Örnekteki AnalyticsAdapter sınıfının etkinliğin bağlamına ihtiyacı olduğunu varsayalım. Aşağıdaki kod, AnalyticsAdapter için etkinlik bağlamının 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ı başlıklı makaleyi inceleyin.

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ı ilgili Android sınıfına yerleştirmekten sorumludur.

Önceki örneklerde Hilt modüllerinde ActivityComponent kullanımı gösterilmişti.

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

Hilt bileşeni Şunun için enjektör:
SingletonComponent Application
ActivityRetainedComponent Yok
ViewModelComponent ViewModel
ActivityComponent Activity
FragmentComponent Fragment
ViewComponent View
ViewWithFragmentComponent View, @WithFragmentBindings ile notlandırdı
ServiceComponent Service

Bileşen ömürleri

Hilt, oluşturulan bileşen sınıflarının örneklerini, ilgili Android sınıflarının yaşam döngüsünü takip ederek otomatik olarak oluşturur ve yok eder.

Oluşturulan bileşen Oluşturulma zamanı Kaldırılma zamanı
SingletonComponent Application#onCreate() Application yok edildi
ActivityRetainedComponent Activity#onCreate() Activity#onDestroy()
ViewModelComponent ViewModel oluşturuldu ViewModel yok edildi
ActivityComponent Activity#onCreate() Activity#onDestroy()
FragmentComponent Fragment#onAttach() Fragment#onDestroy()
ViewComponent View#super() View yok edildi
ViewWithFragmentComponent View#super() View yok edildi
ServiceComponent Service#onCreate() Service#onDestroy()

Bileşen kapsamları

Varsayılan olarak, Hilt'teki tüm bağlamalar kapsamsızdır. Bu, uygulamanız her bağlama isteğinde bulunduğunda Hilt'in gerekli türün yeni bir örneğini oluşturduğu anlamına gelir.

Örnekte, Hilt AnalyticsAdapter öğesini başka bir tür için veya alan yerleştirme yoluyla (ExampleActivity örneğinde olduğu gibi) bağımlılık olarak her sağladığında AnalyticsAdapter öğesinin yeni bir örneğini sağlar.

Ancak Hilt, bağlamanın belirli bir bileşene de kapsamlandırılmasına olanak tanır. Hilt, kapsamı belirlenmiş bağlamanın kapsamının belirlendiği bileşenin örneği başına yalnızca bir kez kapsamı belirlenmiş bağlama oluşturur ve bu bağlama için yapılan 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ırdı ViewWithFragmentComponent @ViewScoped
Service ServiceComponent @ServiceScoped

Örnekte, AnalyticsAdapter kapsamını ActivityComponent olarak ayarlarsanız @ActivityScoped kullanılarak Hilt, ilgili etkinliğin ömrü 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'nın, yalnızca ExampleActivity içinde değil, uygulamanın herhangi bir yerinde her seferinde aynı örneğin kullanılmasını gerektiren bir dahili durumu olduğunu varsayalım. Bu durumda, AnalyticsService'yı SingletonComponent kapsamına almak 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 nasıl kapsamlandırılacağı gösterilmektedir. Bir bağlamanın kapsamı, yüklendiği bileşenin kapsamıyla eşleşmelidir. Bu nedenle, bu örnekte ActivityComponent yerine AnalyticsService öğesini SingletonComponent içine 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 başlıklı makaleyi inceleyin.

Bileşen hiyerarşisi

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

ViewWithFragmentComponent, FragmentComponent'in altındadır. FragmentComponent
    ve ViewComponent, ActivityComponent'ın altındadır. ActivityComponent, ActivityRetainedComponent'in altındadır. ViewModelComponent, ActivityRetainedComponent'ın altındadır. ActivityRetainedComponent ve ServiceComponent
    SingletonComponent'in altındadır.
1. şekil. 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 yerleştirebileceği bir dizi varsayılan bağlama ile birlikte gelir. Bu bağlamaların belirli bir alt sınıfa değil, genel etkinlik ve parça türlerine karşılık geldiğini unutmayın. Bunun nedeni, Hilt'in tüm etkinlikleri yerleştirmek için tek bir etkinlik bileşeni tanımı kullanmasıdır. Her etkinlikte bu bileşenin farklı bir örneği bulunur.

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 kullanılarak da yapılabilir. Örneğin:

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ğlama işlemi @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 sunar. Ancak, Hilt'in desteklemediği sınıflarda alan yerleştirme işlemi yapmanız gerekebilir.

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

Örneğin, Hilt, content providers'ı 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 eklenmiş 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 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 içindeki uygun statik yöntemi kullanın. Parametre, bileşen örneği veya bileşen tutucu görevi 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ında 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 içine yüklendiğinden giriş noktasını almak için ApplicationContext kullanmanız gerekir. Almak istediğiniz bağlama ActivityComponent içinde olsaydı bunun yerine ActivityContext kullanırdınız.

Hilt and Dagger

Hilt, Dagger bağımlılık ekleme kitaplığının üzerine kurulmuştur ve Dagger'ı Android uygulamalarına dahil etmenin standart bir yolunu sunar.

Hilt'in Dagger ile ilgili hedefleri şunlardır:

  • Android uygulamaları için Dagger ile ilgili altyapıyı basitleştirmek amacıyla.
  • Kurulumu, okunabilirliği ve uygulamalar arasında kod paylaşımını kolaylaştırmak için standart bir bileşen ve kapsam grubu oluşturun.
  • Farklı bağlamaları çeşitli derleme türlerine (ör. test, hata ayıklama veya yayın) kolayca sağlama

Android işletim sistemi kendi çerçeve sınıflarının çoğunu oluşturduğundan, bir Android uygulamasında Dagger'ı kullanmak için önemli miktarda standart kod yazmanız gerekir. Hilt, bir Android uygulamasında Dagger kullanmayla ilgili ortak metin kodunu azaltır. Hilt, aşağıdakileri otomatik olarak oluşturur ve sağlar:

  • Android çerçeve sınıflarını Dagger ile entegre etmek için bileşenler. Bu bileşenleri aksi takdirde manuel olarak oluşturmanız gerekir.
  • 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 eden önceden tanımlanmış bağlamalar.
  • @ApplicationContext ve @ActivityContext'ı temsil eden önceden tanımlanmış niteleyiciler.

Dagger ve Hilt kodu aynı kod tabanında birlikte bulunabilir. Ancak çoğu durumda, Android'de Dagger kullanımınızın tamamını yönetmek için Hilt'i kullanmak en iyisidir. Dagger kullanan bir projeyi Hilt'e taşımak için taşıma rehberini ve Dagger uygulamanızı Hilt'e taşıma codelab'ini inceleyin.

Ek kaynaklar

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

Örnekler

Codelab uygulamaları

Bloglar