Hilt के साथ डिपेंडेंसी इंजेक्शन

Hilt, Android के लिए डिपेंडेंसी इंजेक्शन लाइब्रेरी है. यह बॉयलरप्लेट को कम करता है जिसमें मैन्युअल डिपेंडेंसी इंजेक्शन शामिल किया गया हो. मैन्युअल डिपेंडेंसी शुरू करें इंजेक्शन के लिए, आपको हर क्लास और उसकी डिपेंडेंसी को ध्यान में रखते हुए, और कंटेनर का दोबारा इस्तेमाल करने के लिए डिपेंडेंसी मैनेज करें.

Hilt, आपके ऐप्लिकेशन में डीआई का इस्तेमाल करने का स्टैंडर्ड तरीका मुहैया कराता है. इसके लिए, आपके प्रोजेक्ट की हर Android क्लास के लिए कंटेनर और उनके लाइफ़साइकल मैनेज करना स्वचालित रूप से. Hilt को मशहूर डीआई लाइब्रेरी के ऊपर बनाया गया है डैगर: कंपाइल-टाइम में सुधार, रनटाइम की परफ़ॉर्मेंस, स्केलेबिलिटी, और Android Studio सहायता जो डैगर उपलब्ध कराता है. ज़्यादा जानकारी के लिए, हिट और क्लिक करें डैगर.

यह गाइड, Hilt और इसके जनरेट किए गए कंटेनर के बुनियादी सिद्धांतों के बारे में जानकारी देती है. यह इसमें यह जानकारी भी शामिल है कि Hilt का इस्तेमाल करने के लिए, किसी मौजूदा ऐप्लिकेशन को बूटस्ट्रैप कैसे करें.

डिपेंडेंसी जोड़ना

सबसे पहले, अपने प्रोजेक्ट के रूट में hilt-android-gradle-plugin प्लगिन जोड़ें build.gradle फ़ाइल:

ग्रूवी

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
}

इसके बाद, Gradle प्लग इन लागू करें और इन डिपेंडेंसी को अपने app/build.gradle फ़ाइल:

ग्रूवी

...
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 की सुविधाओं का इस्तेमाल करता है. Java 8 को app/build.gradle फ़ाइल में यह जोड़ें:

ग्रूवी

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 का इस्तेमाल करने वाले सभी ऐप्लिकेशन में Application क्लास जिसके साथ एनोटेट किया गया है @HiltAndroidApp.

@HiltAndroidApp, Hilt का कोड जनरेट करने की प्रोसेस ट्रिगर करता है. इसमें, इसके लिए बेस क्लास भी शामिल है आपका ऐप्लिकेशन, जो ऐप्लिकेशन-लेवल डिपेंडेंसी कंटेनर के रूप में काम करता है.

Kotlin

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

Java

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

जनरेट किया गया यह Hilt कॉम्पोनेंट Application ऑब्जेक्ट के साथ अटैच है लाइफ़साइकल होता है और यह इसके लिए डिपेंडेंसी देता है. इसके अलावा, यह पैरंट का एक हिस्सा है, जिसका मतलब है कि अन्य कॉम्पोनेंट निर्भर है जो यह उपलब्ध कराता है.

Android क्लास में डिपेंडेंसी इंजेक्ट करें

एक बार Hilt को आपकी Application क्लास और ऐप्लिकेशन-लेवल में सेट अप कर दिया जाता है कॉम्पोनेंट उपलब्ध है, तो Hilt अन्य Android क्लास के लिए डिपेंडेंसी दे सकता है जिनमें @AndroidEntryPoint एनोटेशन है:

Kotlin

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

Java

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

फ़िलहाल, Hilt इन Android क्लास के साथ काम करता है:

  • Application (@HiltAndroidApp का इस्तेमाल करके)
  • ViewModel (@HiltViewModel का इस्तेमाल करके)
  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

अगर आपको @AndroidEntryPoint की मदद से किसी Android क्लास के बारे में जानकारी देनी है, तो आपको ये काम भी करने होंगे इस पर निर्भर Android क्लास के बारे में बताती हैं. उदाहरण के लिए, अगर आपके पास फ़्रैगमेंट है, तो आपको उन सभी गतिविधियों के बारे में भी जानकारी देनी होगी जहां आप फ़्रैगमेंट.

@AndroidEntryPoint, हर Android के लिए अलग-अलग Hilt कॉम्पोनेंट जनरेट करता है क्लास की शुरुआत की है. ये कॉम्पोनेंट, पब्लिशर के लिए कॉम्पोनेंट में बताए गए, पैरंट क्लास के बारे में जानकारी हैरारकी के हिसाब से खोजना है.

किसी कॉम्पोनेंट से डिपेंडेंसी पाने के लिए, @Inject एनोटेशन का इस्तेमाल करें फ़ील्ड इंजेक्शन:

Kotlin

@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {

  @Inject lateinit var analytics: AnalyticsAdapter
  ...
}

Java

@AndroidEntryPoint
public class ExampleActivity extends AppCompatActivity {

  @Inject
  AnalyticsAdapter analytics;
  ...
}

Hilt इंजेक्ट करने वाली क्लास में अन्य बेस क्लास हो सकती हैं जिनमें इंजेक्शन का भी इस्तेमाल किया जाता है. इन क्लास को @AndroidEntryPoint एनोटेशन की ज़रूरत नहीं होती है, अगर वे ऐब्सट्रैक्ट

Android क्लास को किस लाइफ़साइकल कॉलबैक में इंजेक्ट किया जाता है, इस बारे में ज़्यादा जानने के लिए, कॉम्पोनेंट लाइफ़टाइम देखें.

हिल्ट बाइंडिंग तय करें

फ़ील्ड इंजेक्शन के लिए, Hilt को यह जानने की ज़रूरत है कि यह काम करता है. बाइंडिंग में यह शामिल है डिपेंडेंसी के तौर पर किसी टाइप के इंस्टेंस देने के लिए ज़रूरी जानकारी.

Hilt को ज़रूरी जानकारी देने का एक तरीका कंस्ट्रक्टर इंजेक्शन है. इस्तेमाल की जाने वाली चीज़ें Hilt को यह बताने के लिए कि क्लास के कंस्ट्रक्टर पर @Inject एनोटेशन उस क्लास के इंस्टेंस दें:

Kotlin

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

Java

public class AnalyticsAdapter {

  private final AnalyticsService service;

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

क्लास के एनोटेट किए गए कंस्ट्रक्टर के पैरामीटर, इसकी डिपेंडेंसी उस क्लास को शामिल न करें. उदाहरण में, AnalyticsAdapter के लिए AnalyticsService निर्भर है. इसलिए, Hilt को यह भी पता होना चाहिए कि ऐसे मामले कैसे जोड़े जाएं AnalyticsService.

हिल्ट मॉड्यूल

कभी-कभी किसी टाइप को कंस्ट्रक्टर इंजेक्ट नहीं किया जा सकता. ऐसा कई मामलों में की वजह. उदाहरण के लिए, किसी इंटरफ़ेस को कंस्ट्रक्टर इंजेक्ट नहीं किया जा सकता. आपको यह भी किसी ऐसे टाइप का कंस्ट्रक्टर इंजेक्ट नहीं कर सकता जिसका मालिकाना हक आपके पास न हो, जैसे कि किसी बाहरी लाइब्रेरी का पता लगा सकते हैं. इन मामलों में, Hilt को ज़रूरी जानकारी के साथ उपलब्ध कराया जा सकता है Hilt मॉड्यूल का इस्तेमाल करके ऐसा किया जा सकता है.

Hilt मॉड्यूल ऐसी क्लास है जिसके लिए @Module का इस्तेमाल किया गया है. किसी डैगर की तरह मॉड्यूल है, तो Hilt को कुछ खास तरह के इंस्टेंस उपलब्ध कराने का तरीका बताता है. डैगर मॉड्यूल से अलग, आपको Hilt के बारे में बताने के लिए, Hilt के मॉड्यूल को @InstallIn के साथ एनोटेट करना होगा क्लास में हर मॉड्यूल का इस्तेमाल किया जाएगा या उसे इंस्टॉल किया जाएगा.

Hilt मॉड्यूल में दी जाने वाली डिपेंडेंसी वे कॉम्पोनेंट जो उस Android क्लास से जुड़े होते हैं जिसमें आपने हिल्ट मॉड्यूल.

@Binds की मदद से इंटरफ़ेस इंजेक्ट करें

AnalyticsService के उदाहरण पर गौर करें. अगर AnalyticsService एक इंटरफ़ेस है, तो आप इसे कंस्ट्रक्टर-इंजेक्ट नहीं कर सकते. इसके बजाय, Hilt को बाइंडिंग उपलब्ध कराएं @Binds के साथ एनोटेट करके एक ऐब्स्ट्रैक्ट फ़ंक्शन बनाकर जानकारी हिल्ट मॉड्यूल.

@Binds एनोटेशन से Hilt को पता चलता है कि ज़रूरत पड़ने पर किस फ़ंक्शन का इस्तेमाल करना है इंटरफ़ेस का एक इंस्टेंस दें.

व्याख्या किया गया फ़ंक्शन, Hilt को यह जानकारी देता है:

  • फ़ंक्शन के रिटर्न टाइप से Hilt के बारे में जानकारी मिलती है कि फ़ंक्शन कौनसा इंटरफ़ेस देता है के उदाहरण.
  • फ़ंक्शन पैरामीटर Hilt को बताता है कि कौनसा फ़ंक्शन देना है.

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 मॉड्यूल AnalyticsModule के साथ एनोटेट किया गया है @InstallIn(ActivityComponent.class) क्योंकि आप चाहते हैं कि Hilt उसे इंजेक्ट करे ExampleActivity पर निर्भर है. इस एनोटेशन का मतलब है कि AnalyticsModule में डिपेंडेंसी, ऐप्लिकेशन की सभी गतिविधियों के लिए उपलब्ध है.

@Providers से इंस्टेंस इंजेक्ट करें

इंटरफ़ेस ही सिर्फ़ ऐसा मामला नहीं है जिसमें किसी टाइप को कंस्ट्रक्टर इंजेक्ट नहीं किया जा सकता. अगर आप क्लास के मालिक नहीं हैं, तो भी कंस्ट्रक्टर इंजेक्शन नहीं किया जा सकता, क्योंकि एक बाहरी लाइब्रेरी से आता है (क्लास Retrofit, OkHttpClient, या रूम डेटाबेस) या अगर इंस्टेंस ज़रूरी हैं बिल्डर की सहायता से बनाए जाएं पैटर्न.

ऊपर दिए गए उदाहरण पर गौर करें. अगर आपके पास सीधे तौर पर AnalyticsService का मालिकाना हक नहीं है क्लास में है, तो आप एक फ़ंक्शन को एक Hilt मॉड्यूल के अंदर इकट्ठा करता है और उस फ़ंक्शन की @Provides के साथ व्याख्या करता है.

व्याख्या किया गया फ़ंक्शन, Hilt को यह जानकारी उपलब्ध कराता है:

  • फ़ंक्शन के रिटर्न टाइप से Hilt के बारे में पता चलता है कि फ़ंक्शन किस टाइप के इंस्टेंस देता है में से.
  • फ़ंक्शन पैरामीटर, इससे जुड़े टाइप की डिपेंडेंसी को Hilt के बारे में बताते हैं.
  • फ़ंक्शन का मुख्य हिस्सा, Hilt को इससे जुड़ा एक इंस्टेंस देने का तरीका बताता है टाइप करें. Hilt, फ़ंक्शन को हर बार कार्रवाई करने के लिए एक्ज़ीक्यूट करता है दर्ज करें.

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);
  }
}

एक ही टाइप के लिए एक से ज़्यादा बाइंडिंग उपलब्ध कराएं

ऐसे मामलों में जहां आपको Hilt की ज़रूरत है, ताकि आप उसे अलग-अलग तरीके से लागू कर सकें टाइप करना होगा, तो आपको Hilt को एक से ज़्यादा बाइंडिंग के साथ उपलब्ध कराना होगा. आप क्वालिफ़ायर की मदद से, एक ही टाइप के लिए एक से ज़्यादा बाइंडिंग तय करें.

क्वालीफ़ायर वह जानकारी होती है जिसका इस्तेमाल किसी टाइप करें, जब उस टाइप की एक से ज़्यादा बाइंडिंग हों.

उदाहरण पर ध्यान दें. अगर आपको AnalyticsService पर आने वाले कॉल को रोकना है, तो एक OkHttpClient ऑब्जेक्ट का इस्तेमाल इंटरसेप्टर होना चाहिए. इसके लिए कॉल को किसी अन्य तरीके से रोकना पड़ सकता है. इसमें केस में, आपको Hilt को यह बताना होगा कि वे OkHttpClient.

सबसे पहले, उन क्वालिफ़ायर के बारे में बताएं जिनका इस्तेमाल आपको @Binds के बारे में बताने के लिए करना है या @Provides तरीके:

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 {}

इसके बाद, Hilt को यह जानने की ज़रूरत है कि उस टाइप का इंस्टेंस कैसे दिया जाए जो हर क्वालीफ़ायर के साथ. इस मामले में, @Provides के साथ Hilt मॉड्यूल का इस्तेमाल किया जा सकता है. दोनों तरीकों में रिटर्न टाइप एक ही होता है, लेकिन क्वालीफ़ायर उन्हें दो के तौर पर लेबल करता है अलग-अलग बाइंडिंग:

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

अपनी ज़रूरत के हिसाब से कोई खास टाइप डालने के लिए, फ़ील्ड की जानकारी दें या मिलते-जुलते क्वालीफ़ायर के साथ पैरामीटर:

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;
  ...
}

सबसे सही तरीका यह है कि अगर किसी टाइप में क्वालीफ़ायर जोड़ा जाता है, तो की अनुमति देता है. बेस या आम को छोड़ना क्वालीफ़ायर के बिना लागू करने पर गड़बड़ी की संभावना होती है और इससे Hilt हो सकता है गलत डिपेंडेंसी डालना.

Hilt में पहले से तय क्वालीफ़ायर

Hilt, पहले से तय किए गए कुछ क्वालिफ़ायर देता है. उदाहरण के लिए, आपको अभी इसकी ज़रूरत पड़ सकती है ऐप्लिकेशन या गतिविधि से Context क्लास, Hilt यह जानकारी देता है @ApplicationContext और @ActivityContext क्वालिफ़ायर.

मान लें कि उदाहरण की AnalyticsAdapter क्लास को गतिविधि. इस कोड में, गतिविधि की जानकारी देने का तरीका बताया गया है AnalyticsAdapter के लिए संदर्भ:

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 में उपलब्ध अन्य पहले से तय बाइंडिंग के लिए, घटक डिफ़ॉल्ट देखें बाइंडिंग.

Android क्लास के लिए जनरेट किए गए कॉम्पोनेंट

हर उस Android क्लास के लिए जिसमें फ़ील्ड इंजेक्शन लिया जा सकता है, असोसिएटेड हिल्ट कॉम्पोनेंट, जिसे @InstallIn एनोटेशन में देखा जा सकता है. हर Hilt कॉम्पोनेंट, अपनी बाइंडिंग को संबंधित Android क्लास.

पिछले उदाहरणों में, Hilt में ActivityComponent के इस्तेमाल के बारे में बताया गया है मॉड्यूल देखें.

Hilt में ये कॉम्पोनेंट हैं:

हिलने वाला कॉम्पोनेंट इंजेक्टर
SingletonComponent Application
ActivityRetainedComponent लागू नहीं
ViewModelComponent ViewModel
ActivityComponent Activity
FragmentComponent Fragment
ViewComponent View
ViewWithFragmentComponent View ने @WithFragmentBindings की व्याख्या की
ServiceComponent Service

कॉम्पोनेंट की लाइफ़टाइम गतिविधि

Hilt, जनरेट किए गए कॉम्पोनेंट क्लास के इंस्टेंस बनाता और खत्म करता है नीचे दिए गए चरण पूरे करने के लिए, ज़रूरी डेटा इकट्ठा किया जा सकता है.

जनरेट किया गया कॉम्पोनेंट मैसेज किस समय लिखा गया इस पर नष्ट किया गया
SingletonComponent Application#onCreate() Application खत्म किया गया
ActivityRetainedComponent Activity#onCreate() Activity#onDestroy()
ViewModelComponent ViewModel बनाया गया ViewModel खत्म किया गया
ActivityComponent Activity#onCreate() Activity#onDestroy()
FragmentComponent Fragment#onAttach() Fragment#onDestroy()
ViewComponent View#super() View खत्म किया गया
ViewWithFragmentComponent View#super() View खत्म किया गया
ServiceComponent Service#onCreate() Service#onDestroy()

कॉम्पोनेंट के स्कोप

डिफ़ॉल्ट रूप से, Hilt में सभी बाइंडिंग बिना स्कोप वाली होती हैं. इसका मतलब है कि हर बार आपके ऐप्लिकेशन बाइंडिंग का अनुरोध करता है, तो Hilt ज़रूरी टाइप का एक नया इंस्टेंस बनाता है.

इस उदाहरण में, जब भी Hilt, AnalyticsAdapter को डिपेंडेंसी के तौर पर इस पर निर्भर करता है किसी अन्य टाइप या फ़ील्ड इंजेक्शन (जैसा कि ExampleActivity में है) के ज़रिए, Hilt उपलब्ध कराता है AnalyticsAdapter का नया इंस्टेंस.

हालांकि, Hilt, बाइंडिंग को किसी खास कॉम्पोनेंट तक के दायरे में लाने की अनुमति भी देता है. हिल्ट उस कॉम्पोनेंट के हर इंस्टेंस के लिए सिर्फ़ एक बार स्कोप वाली बाइंडिंग बनाता है जिसका इस्तेमाल करके बाइंडिंग का दायरा तक सीमित है और बाइंडिंग के लिए सभी अनुरोध एक ही इंस्टेंस शेयर करते हैं.

नीचे दी गई टेबल में, जनरेट किए गए हर कॉम्पोनेंट के लिए स्कोप एनोटेशन की सूची दी गई है:

Android क्लास जनरेट किया गया कॉम्पोनेंट दायरा
Application SingletonComponent @Singleton
Activity ActivityRetainedComponent @ActivityRetainedScoped
ViewModel ViewModelComponent @ViewModelScoped
Activity ActivityComponent @ActivityScoped
Fragment FragmentComponent @FragmentScoped
View ViewComponent @ViewScoped
View ने @WithFragmentBindings की व्याख्या की ViewWithFragmentComponent @ViewScoped
Service ServiceComponent @ServiceScoped

इस उदाहरण में, अगर AnalyticsAdapter को ActivityComponent तक सीमित किया गया है @ActivityScoped का इस्तेमाल करने पर, Hilt AnalyticsAdapter का वही इंस्टेंस देता है की अवधि के हिसाब से:

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 में एक अंदरूनी स्थिति है, जिसे इंस्टेंस हर बार इस्तेमाल करना चाहिए—सिर्फ़ ExampleActivity में ही नहीं, बल्कि ऐप खोलें. इस मामले में, AnalyticsService का दायरा SingletonComponent. इसका नतीजा यह होता है कि जब भी कॉम्पोनेंट को AnalyticsService का एक इंस्टेंस दें, यह हर बार समान इंस्टेंस देता है समय.

नीचे दिए गए उदाहरण में, एक कॉम्पोनेंट में बाइंडिंग का दायरा बढ़ाने का तरीका बताया गया है. हिल्ट मॉड्यूल. बाइंडिंग का स्कोप, कॉम्पोनेंट के स्कोप से मेल खाना चाहिए, जहां यह इंस्टॉल किया है, इसलिए इस उदाहरण में आपको AnalyticsService को ActivityComponent के बजाय SingletonComponent:

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 के कॉम्पोनेंट के स्कोप के बारे में ज़्यादा जानने के लिए, Android में स्कोप करना और हिलना.

कॉम्पोनेंट की हैरारकी

किसी कॉम्पोनेंट में मॉड्यूल इंस्टॉल करने से, इसकी बाइंडिंग को उस कॉम्पोनेंट या नीचे दिए गए किसी भी चाइल्ड कॉम्पोनेंट में, अन्य बाइंडिंग की डिपेंडेंसी इसे कॉम्पोनेंट की हैरारकी में:

ViewWithफ़्रैगमेंट कॉम्पोनेंट, फ़्रैगमेंट कॉम्पोनेंट में मौजूद है. फ़्रैगमेंट कॉम्पोनेंट
    और Viewcomponent ऐक्टिविटी कॉम्पोनेंट के नीचे मौजूद होते हैं. ऐक्टिविटीकॉम्पोनेंट इसके अंतर्गत है
    ऐक्टिविटी बरकरार रखे जाने वाले कॉम्पोनेंट. ViewModelcomponents है
    ऐक्टिविटी बरकरार रखे जाने वाले कॉम्पोनेंट. ऐक्टिविटी बरकरार रखे जाने वाले कंपोनेंट और सर्विसकॉम्पोनेंट
    सिंगलटन कॉम्पोनेंट के नीचे मौजूद हैं.
पहली इमेज. Hilt के कॉम्पोनेंट की हैरारकी जनरेट करता है.

कॉम्पोनेंट की डिफ़ॉल्ट बाइंडिंग

Hilt का हर कॉम्पोनेंट, डिफ़ॉल्ट बाइंडिंग के एक सेट के साथ आता है. इसे Hilt इस तौर पर इंजेक्ट कर सकता है डिपेंडेंसी को अपनी कस्टम बाइंडिंग में डालें. ध्यान दें कि ये बाइंडिंग मेल खाती हैं सामान्य गतिविधि और फ़्रैगमेंट टाइप के साथ-साथ किसी खास सब-क्लास के लिए भी इस्तेमाल किया जा सकता है. ऐसा इसलिए है, क्योंकि Hilt एक गतिविधि वाले कॉम्पोनेंट की परिभाषा का इस्तेमाल करके सभी को इंजेक्ट करता है गतिविधियां. हर गतिविधि में इस कॉम्पोनेंट का अलग-अलग इंस्टेंस होता है.

Android घटक डिफ़ॉल्ट बाइंडिंग
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

@ApplicationContext का इस्तेमाल करके भी ऐप्लिकेशन कॉन्टेक्स्ट बाइंडिंग उपलब्ध है. उदाहरण के लिए:

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;
  }
}

@ActivityContext का इस्तेमाल करने पर, गतिविधि कॉन्टेक्स्ट बाइंडिंग भी उपलब्ध है. इसके लिए उदाहरण:

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 के साथ काम नहीं करती हैं

Hilt, सबसे आम Android क्लास के साथ काम करता है. हालांकि, आपको ऐसी क्लास में फ़ील्ड इंजेक्शन लेने की ज़रूरत है जो Hilt के साथ काम नहीं करता.

ऐसे मामलों में, @EntryPoint का इस्तेमाल करके एंट्री पॉइंट बनाया जा सकता है एनोटेशन. एंट्री पॉइंट, कोड के बीच की सीमा होती है. इसे Hilt की मदद से मैनेज किया जाता है और कई कोड हैं. यह वह बिंदु है जहां कोड सबसे पहले ऐसी ऑब्जेक्ट हैं जिन्हें Hilt प्रबंधित करता है. एंट्री पॉइंट, Hilt के लिए उस कोड का इस्तेमाल करने की अनुमति देते हैं जो Hilt करता है डिपेंडेंसी ग्राफ़ में डिपेंडेंसी देने के लिए मैनेज नहीं किया जा सकता.

उदाहरण के लिए, Hilt सीधे तौर पर कॉन्टेंट के साथ काम नहीं करता सेवा देने वाली कंपनियां. अगर आपको कोई कॉन्टेंट चाहिए प्रोवाइडर को Hilt का इस्तेमाल करने की ज़रूरत है. इसके लिए, आपको एक इंटरफ़ेस जिसे आपकी पसंद के हर बाइंडिंग टाइप के लिए @EntryPoint के साथ एनोटेट किया गया हो और क्वालिफ़ायर शामिल होते हैं. इसके बाद, उस कॉम्पोनेंट के बारे में बताने के लिए @InstallIn जोड़ें जिसमें एंट्री पॉइंट को इस तरह इंस्टॉल करें:

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

किसी एंट्री पॉइंट को ऐक्सेस करने के लिए, EntryPointAccessors. पैरामीटर या तो कॉम्पोनेंट इंस्टेंस होना चाहिए या @AndroidEntryPoint ऑब्जेक्ट, जो कॉम्पोनेंट होल्डर के तौर पर काम करता है. पक्का करें कि पैरामीटर के तौर पर पास किया गया कॉम्पोनेंट और EntryPointAccessors स्टैटिक वे दोनों @InstallIn एनोटेशन में Android क्लास से मेल खाते हैं @EntryPoint इंटरफ़ेस:

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

इस उदाहरण में, एंट्री वापस पाने के लिए, आपको ApplicationContext का इस्तेमाल करना होगा पॉइंट, क्योंकि SingletonComponent में एंट्री पॉइंट इंस्टॉल किया गया है. अगर बाइंडिंग जिसे आप वापस पाना चाहते थे, वह ActivityComponent में थी, तो आप इसके बजाय ActivityContext का इस्तेमाल करें.

हिल्ट ऐंड डैगर

हिल्ट, डैगर के ऊपर बना है डिपेंडेंसी इंजेक्शन लाइब्रेरी, डैगर को शामिल करने का स्टैंडर्ड तरीका देती है Android ऐप्लिकेशन में बदल सकते हैं.

डैगर के संबंध में, Hilt के लक्ष्य इस तरह हैं:

  • Android ऐप्लिकेशन के लिए डैगर से जुड़े इन्फ़्रास्ट्रक्चर को आसान बनाने के लिए.
  • आसानी से सेटअप और आसानी से समझने के लिए, कॉम्पोनेंट और स्कोप का स्टैंडर्ड सेट बनाने के लिए, और ऐप्लिकेशन के बीच कोड शेयर करना.
  • अलग-अलग बिल्ड टाइप में अलग-अलग बाइंडिंग का प्रावधान करने का आसान तरीका देने के लिए, जैसे, टेस्टिंग, डीबग या रिलीज़.

ऐसा इसलिए, क्योंकि Android ऑपरेटिंग सिस्टम अपने कई फ़्रेमवर्क को इंस्टैंशिएट करता है क्लास में, Android ऐप्लिकेशन में डैगर का इस्तेमाल करने के लिए, आपको बॉयलरप्लेट की मात्रा. हिल्ट उस बॉयलरप्लेट कोड को कम कर देता है जो इसमें शामिल है Android ऐप्लिकेशन में डैगर का इस्तेमाल करके. Hilt अपने-आप जनरेट होता है और यह जानकारी उपलब्ध कराता है:

  • डैगर के साथ Android फ़्रेमवर्क क्लास को इंटिग्रेट करने के लिए कॉम्पोनेंट नहीं तो मैन्युअल तरीके से बनाने पड़ते थे.
  • Hilt के जनरेट किए गए कॉम्पोनेंट के साथ इस्तेमाल करने के लिए स्कोप की जानकारी स्वचालित रूप से.
  • Application या Android क्लास जैसी Android क्लास को दिखाने के लिए पहले से तय बाइंडिंग Activity.
  • @ApplicationContext और को दर्शाने के लिए पहले से तय क्वालीफ़ायर @ActivityContext.

डैगर और हिल्ट कोड, एक ही कोड बेस में एक साथ रह सकते हैं. हालांकि, ज़्यादातर मामलों में Android पर डैगर के इस्तेमाल को मैनेज करने के लिए, Hilt का इस्तेमाल करें. माइग्रेट करने के लिए डैगर टू हिल्ट का इस्तेमाल करने वाला प्रोजेक्ट है, तो माइग्रेशन देखें गाइड और माइग्रेट करने की सुविधा Hilt के लिए आपका डैगर ऐप्लिकेशन कोडलैब (कोड बनाना सीखना).

अन्य संसाधन

Hilt के बारे में ज़्यादा जानने के लिए, नीचे दिए गए अतिरिक्त संसाधन देखें.

सैंपल

कोड लैब

ब्लॉग