হিল্টের সাথে নির্ভরতা ইনজেকশন

হিল্ট হ'ল অ্যান্ড্রয়েডের জন্য একটি নির্ভরতা ইনজেকশন লাইব্রেরি যা আপনার প্রকল্পে ম্যানুয়াল নির্ভরতা ইনজেকশন করার বয়লারপ্লেটকে হ্রাস করে। ম্যানুয়াল ডিপেন্ডেন্সি ইনজেকশন করার জন্য আপনাকে প্রতিটি শ্রেণী এবং এর নির্ভরতাগুলিকে হাতে তৈরি করতে হবে এবং নির্ভরতাগুলি পুনরায় ব্যবহার এবং পরিচালনা করতে পাত্রে ব্যবহার করতে হবে।

হিল্ট আপনার প্রজেক্টের প্রতিটি অ্যান্ড্রয়েড ক্লাসের জন্য কন্টেইনার সরবরাহ করে এবং তাদের জীবনচক্র স্বয়ংক্রিয়ভাবে পরিচালনা করে আপনার অ্যাপ্লিকেশনে DI ব্যবহার করার একটি আদর্শ উপায় প্রদান করে। হিল্ট জনপ্রিয় DI লাইব্রেরি Dagger- এর উপরে তৈরি করা হয়েছে কম্পাইল-টাইম শুদ্ধতা, রানটাইম পারফরম্যান্স, স্কেলেবিলিটি এবং অ্যান্ড্রয়েড স্টুডিও সমর্থন যা Dagger প্রদান করে। আরও তথ্যের জন্য, হিল্ট এবং ড্যাগার দেখুন।

এই নির্দেশিকাটি হিল্ট এবং এর তৈরি পাত্রের মৌলিক ধারণাগুলি ব্যাখ্যা করে। এটি হিল্ট ব্যবহার করার জন্য একটি বিদ্যমান অ্যাপকে কীভাবে বুটস্ট্র্যাপ করতে হয় তার একটি প্রদর্শনও অন্তর্ভুক্ত করে।

নির্ভরতা যোগ করা হচ্ছে

প্রথমে, আপনার প্রোজেক্টের রুট build.gradle ফাইলে hilt-android-gradle-plugin প্লাগইন যোগ করুন:

গ্রোভি

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

কোটলিন

plugins {
  ...
  id("com.google.dagger.hilt.android") version "2.51.1" 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.51.1"
  kapt "com.google.dagger:hilt-compiler:2.51.1"
}

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

কোটলিন

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

android {
  ...
}

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

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

হিল্ট জাভা 8 বৈশিষ্ট্য ব্যবহার করে। আপনার প্রকল্পে Java 8 সক্ষম করতে, app/build.gradle ফাইলে নিম্নলিখিতগুলি যোগ করুন:

গ্রোভি

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

কোটলিন

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

হিল্ট অ্যাপ্লিকেশন ক্লাস

হিল্ট ব্যবহার করে এমন সব অ্যাপে অবশ্যই @HiltAndroidApp এর সাথে টীকাযুক্ত একটি Application ক্লাস থাকতে হবে।

@HiltAndroidApp হিল্টের কোড জেনারেশন ট্রিগার করে, আপনার অ্যাপ্লিকেশনের জন্য একটি বেস ক্লাস সহ যা অ্যাপ্লিকেশন-স্তরের নির্ভরতা ধারক হিসাবে কাজ করে।

কোটলিন

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

জাভা

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

এই উৎপন্ন হিল্ট উপাদানটি Application অবজেক্টের জীবনচক্রের সাথে সংযুক্ত থাকে এবং এটির উপর নির্ভরতা প্রদান করে। অতিরিক্তভাবে, এটি অ্যাপটির মূল উপাদান, যার অর্থ অন্যান্য উপাদানগুলি এটি সরবরাহ করে এমন নির্ভরতাগুলি অ্যাক্সেস করতে পারে।

অ্যান্ড্রয়েড ক্লাসে নির্ভরতা ইনজেক্ট করুন

একবার আপনার Application ক্লাসে হিল্ট সেট আপ হয়ে গেলে এবং একটি অ্যাপ্লিকেশন-স্তরের উপাদান উপলব্ধ হলে, হিল্ট অন্যান্য অ্যান্ড্রয়েড ক্লাসগুলিতে নির্ভরতা প্রদান করতে পারে যেখানে @AndroidEntryPoint টীকা রয়েছে:

কোটলিন

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

জাভা

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

হিল্ট বর্তমানে নিম্নলিখিত অ্যান্ড্রয়েড ক্লাসগুলিকে সমর্থন করে:

  • Application ( @HiltAndroidApp ব্যবহার করে)
  • ViewModel ( @HiltViewModel ব্যবহার করে)
  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

আপনি যদি @AndroidEntryPoint এর সাথে একটি অ্যান্ড্রয়েড ক্লাস টীকা করেন, তাহলে আপনাকে অবশ্যই এটির উপর নির্ভরশীল অ্যান্ড্রয়েড ক্লাসগুলিকে টীকা করতে হবে৷ উদাহরণস্বরূপ, যদি আপনি একটি খণ্ডটি টীকা করেন, তাহলে আপনাকে অবশ্যই যে কোনো ক্রিয়াকলাপকে টীকা দিতে হবে যেখানে আপনি সেই খণ্ডটি ব্যবহার করেন।

@AndroidEntryPoint আপনার প্রজেক্টের প্রতিটি অ্যান্ড্রয়েড ক্লাসের জন্য একটি পৃথক হিল্ট উপাদান তৈরি করে। এই উপাদানগুলি তাদের নিজ নিজ অভিভাবক শ্রেণী থেকে কম্পোনেন্ট শ্রেণিবিন্যাসে বর্ণিত নির্ভরতা পেতে পারে।

একটি উপাদান থেকে নির্ভরতা পেতে, ক্ষেত্র ইনজেকশন সঞ্চালনের জন্য @Inject টীকাটি ব্যবহার করুন:

কোটলিন

@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {

  @Inject lateinit var analytics: AnalyticsAdapter
  ...
}

জাভা

@AndroidEntryPoint
public class ExampleActivity extends AppCompatActivity {

  @Inject
  AnalyticsAdapter analytics;
  ...
}

যে ক্লাসগুলি হিল্ট ইনজেকশন দেয় সেগুলির অন্যান্য বেস ক্লাস থাকতে পারে যেগুলি ইনজেকশনও ব্যবহার করে। এই ক্লাসগুলির @AndroidEntryPoint টীকা প্রয়োজন নেই যদি সেগুলি বিমূর্ত হয়।

কোন Android ক্লাসে লাইফসাইকেল কলব্যাক ইনজেক্ট করা হয় সে সম্পর্কে আরও জানতে, কম্পোনেন্ট লাইফটাইম দেখুন।

হিল্ট বাইন্ডিং সংজ্ঞায়িত করুন

ফিল্ড ইনজেকশন সঞ্চালনের জন্য, হিল্টকে সংশ্লিষ্ট উপাদান থেকে প্রয়োজনীয় নির্ভরতার উদাহরণগুলি কীভাবে সরবরাহ করতে হয় তা জানতে হবে। একটি বাইন্ডিং একটি নির্ভরতা হিসাবে একটি ধরনের দৃষ্টান্ত প্রদান করার জন্য প্রয়োজনীয় তথ্য ধারণ করে।

হিল্টে আবদ্ধ তথ্য প্রদানের একটি উপায় হল কনস্ট্রাক্টর ইনজেকশন । একটি ক্লাসের কনস্ট্রাক্টরের উপর @Inject টীকাটি ব্যবহার করুন হিল্টকে কীভাবে সেই ক্লাসের দৃষ্টান্ত প্রদান করতে হয় তা জানাতে:

কোটলিন

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

জাভা

public class AnalyticsAdapter {

  private final AnalyticsService service;

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

একটি ক্লাসের টীকাযুক্ত কনস্ট্রাক্টরের পরামিতি হল সেই শ্রেণীর নির্ভরতা। উদাহরণে, AnalyticsAdapter একটি নির্ভরতা হিসাবে AnalyticsService রয়েছে৷ তাই, হিল্টকেও জানতে হবে কিভাবে AnalyticsService উদাহরণ প্রদান করতে হয়।

হিল্ট মডিউল

কখনও কখনও একটি টাইপ কনস্ট্রাক্টর-ইনজেক্ট করা যায় না। এটি একাধিক কারণে ঘটতে পারে। উদাহরণস্বরূপ, আপনি একটি ইন্টারফেস কনস্ট্রাক্টর-ইনজেক্ট করতে পারবেন না। আপনি এমন একটি টাইপ কনস্ট্রাক্টর-ইনজেক্ট করতে পারবেন না যা আপনার নিজের নয়, যেমন একটি বহিরাগত লাইব্রেরি থেকে একটি ক্লাস। এই ক্ষেত্রে, আপনি Hilt মডিউল ব্যবহার করে বাঁধাই তথ্য সহ Hilt প্রদান করতে পারেন।

একটি হিল্ট মডিউল হল একটি ক্লাস যা @Module দিয়ে টীকা করা হয়। একটি ড্যাগার মডিউলের মতো, এটি হিল্টকে জানায় যে কীভাবে নির্দিষ্ট ধরণের উদাহরণ প্রদান করতে হয়। Dagger মডিউলের বিপরীতে, আপনাকে হিল্ট মডিউলগুলিকে @InstallIn সাথে টীকা করতে হবে যাতে হিল্টকে বলা যায় যে প্রতিটি মডিউল কোন অ্যান্ড্রয়েড ক্লাসে ব্যবহার বা ইনস্টল করা হবে।

আপনি হিল্ট মডিউলে যে নির্ভরতাগুলি প্রদান করেন সেগুলি সমস্ত জেনারেট হওয়া উপাদানগুলিতে উপলব্ধ যা Android ক্লাসের সাথে যুক্ত যেখানে আপনি হিল্ট মডিউল ইনস্টল করেন৷

@Binds এর সাথে ইন্টারফেস ইনস্ট্যান্স ইনজেক্ট করুন

AnalyticsService উদাহরণ বিবেচনা করুন. AnalyticsService যদি একটি ইন্টারফেস হয়, তাহলে আপনি এটি কনস্ট্রাক্টর-ইনজেক্ট করতে পারবেন না। পরিবর্তে, হিল্ট মডিউলের ভিতরে @Binds এর সাথে টীকাযুক্ত একটি বিমূর্ত ফাংশন তৈরি করে বাইন্ডিং তথ্য সহ Hilt প্রদান করুন।

@Binds টীকাটি হিল্টকে বলে যে কোন প্রয়োগটি ব্যবহার করতে হবে যখন এটি একটি ইন্টারফেসের একটি উদাহরণ প্রদান করতে হবে।

টীকাকৃত ফাংশন হিল্টকে নিম্নলিখিত তথ্য সরবরাহ করে:

  • ফাংশন রিটার্ন টাইপ হিল্টকে বলে যে ফাংশনটি কোন ইন্টারফেসের উদাহরণ প্রদান করে।
  • ফাংশন প্যারামিটার হিল্টকে বলে যে কোন বাস্তবায়ন প্রদান করতে হবে।

কোটলিন

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
}

জাভা

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

হিল্ট মডিউল AnalyticsModule @InstallIn(ActivityComponent.class) দিয়ে টীকা করা হয়েছে কারণ আপনি চান যে হিল্ট সেই নির্ভরতা ExampleActivity তে ইনজেক্ট করুক। এই টীকাটির অর্থ হল AnalyticsModule সমস্ত নির্ভরতা অ্যাপের সমস্ত কার্যকলাপে উপলব্ধ।

@Provides দিয়ে ইনজেকশন ইনজেকশন করুন

ইন্টারফেসগুলি একমাত্র ক্ষেত্রে নয় যেখানে আপনি একটি টাইপ কনস্ট্রাক্টর-ইনজেক্ট করতে পারবেন না। আপনি যদি ক্লাসের মালিক না হন তবে কনস্ট্রাক্টর ইনজেকশনও সম্ভব নয় কারণ এটি একটি বাহ্যিক লাইব্রেরি থেকে আসে (শ্রেণীগুলি যেমন Retrofit , OkHttpClient , বা রুম ডেটাবেস ), অথবা যদি উদাহরণগুলি অবশ্যই বিল্ডার প্যাটার্নের সাথে তৈরি করা উচিত।

আগের উদাহরণ বিবেচনা করুন। আপনি যদি সরাসরি AnalyticsService ক্লাসের মালিক না হন, তাহলে আপনি হিল্ট মডিউলের ভিতরে একটি ফাংশন তৈরি করে এবং @Provides এর সাথে সেই ফাংশনটি টীকা দিয়ে কীভাবে এই ধরনের উদাহরণ প্রদান করবেন তা হিল্টকে বলতে পারেন।

টীকাকৃত ফাংশন হিল্টে নিম্নলিখিত তথ্য সরবরাহ করে:

  • ফাংশন রিটার্ন টাইপ হিল্টকে বলে যে ফাংশনটি কোন ধরনের উদাহরণ প্রদান করে।
  • ফাংশন প্যারামিটারগুলি হিল্টকে সংশ্লিষ্ট প্রকারের নির্ভরতা বলে।
  • ফাংশন বডি হিল্টকে বলে কিভাবে সংশ্লিষ্ট ধরনের একটি উদাহরণ প্রদান করতে হয়। হিল্ট প্রতিবার ফাংশন বডিকে সেই ধরনের একটি উদাহরণ প্রদান করার প্রয়োজনে কার্যকর করে।

কোটলিন

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

জাভা

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

একই ধরনের জন্য একাধিক বাইন্ডিং প্রদান করুন

যে ক্ষেত্রে আপনার নির্ভরতা হিসাবে একই ধরণের বিভিন্ন বাস্তবায়ন প্রদানের জন্য হিল্টের প্রয়োজন, আপনাকে অবশ্যই একাধিক বাইন্ডিং সহ হিল্ট প্রদান করতে হবে। আপনি কোয়ালিফায়ারগুলির সাথে একই ধরণের জন্য একাধিক বাইন্ডিং সংজ্ঞায়িত করতে পারেন।

একটি কোয়ালিফায়ার হল একটি টীকা যা আপনি একটি টাইপের জন্য একটি নির্দিষ্ট বাইন্ডিং সনাক্ত করতে ব্যবহার করেন যখন সেই টাইপের একাধিক বাইন্ডিং সংজ্ঞায়িত থাকে।

উদাহরণ বিবেচনা করুন। আপনার যদি AnalyticsService কল ইন্টারসেপ্ট করতে হয়, তাহলে আপনি ইন্টারসেপ্টর সহ একটি OkHttpClient অবজেক্ট ব্যবহার করতে পারেন। অন্যান্য পরিষেবাগুলির জন্য, আপনাকে অন্যভাবে কলগুলিকে বাধা দিতে হতে পারে৷ সেই ক্ষেত্রে, আপনাকে হিল্টকে বলতে হবে কিভাবে OkHttpClient এর দুটি ভিন্ন বাস্তবায়ন প্রদান করতে হয়।

প্রথমে, @Binds বা @Provides পদ্ধতিগুলিকে টীকা করতে আপনি যে কোয়ালিফায়ারগুলি ব্যবহার করবেন তা নির্ধারণ করুন:

কোটলিন

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

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

জাভা

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

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

তারপরে, হিল্টকে জানতে হবে কিভাবে প্রতিটি কোয়ালিফায়ারের সাথে সঙ্গতিপূর্ণ ধরনের একটি উদাহরণ প্রদান করতে হয়। এই ক্ষেত্রে, আপনি @Provides এর সাথে একটি হিল্ট মডিউল ব্যবহার করতে পারেন। উভয় পদ্ধতিরই একই রিটার্ন টাইপ আছে, কিন্তু কোয়ালিফায়াররা তাদের দুটি ভিন্ন বাইন্ডিং হিসেবে লেবেল করে:

কোটলিন

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

জাভা

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

আপনি সংশ্লিষ্ট কোয়ালিফায়ারের সাথে ক্ষেত্র বা পরামিতি টীকা করে আপনার প্রয়োজনীয় নির্দিষ্ট প্রকারটি ইনজেক্ট করতে পারেন:

কোটলিন

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

জাভা

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

একটি সর্বোত্তম অনুশীলন হিসাবে, আপনি যদি একটি প্রকারে একটি যোগ্যতা যোগ করেন, সেই নির্ভরতা প্রদানের সমস্ত সম্ভাব্য উপায়ে যোগ্যতা যোগ করুন। একটি কোয়ালিফায়ার ছাড়া বেস বা সাধারণ বাস্তবায়ন ত্যাগ করা ত্রুটি-প্রবণ এবং এর ফলে হিল্ট ভুল নির্ভরতা ইনজেকশন করতে পারে।

হিল্টে পূর্বনির্ধারিত কোয়ালিফায়ার

হিল্ট কিছু পূর্বনির্ধারিত কোয়ালিফায়ার প্রদান করে। উদাহরণস্বরূপ, অ্যাপ্লিকেশন বা কার্যকলাপ থেকে আপনার Context ক্লাসের প্রয়োজন হতে পারে, হিল্ট @ApplicationContext এবং @ActivityContext কোয়ালিফায়ার প্রদান করে।

ধরুন যে উদাহরণ থেকে AnalyticsAdapter ক্লাসের কার্যকলাপের প্রসঙ্গ প্রয়োজন। নিম্নলিখিত কোডটি দেখায় কিভাবে AnalyticsAdapter কার্যকলাপের প্রসঙ্গ প্রদান করতে হয়:

কোটলিন

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

জাভা

public class AnalyticsAdapter {

  private final Context context;
  private final AnalyticsService service;

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

হিল্টে উপলব্ধ অন্যান্য পূর্বনির্ধারিত বাইন্ডিংয়ের জন্য, কম্পোনেন্ট ডিফল্ট বাইন্ডিং দেখুন।

অ্যান্ড্রয়েড ক্লাসের জন্য তৈরি উপাদান

প্রতিটি অ্যান্ড্রয়েড ক্লাসের জন্য যেখানে আপনি ফিল্ড ইনজেকশন করতে পারেন, সেখানে একটি সংশ্লিষ্ট হিল্ট উপাদান রয়েছে যা আপনি @InstallIn টীকাতে উল্লেখ করতে পারেন। প্রতিটি হিল্ট উপাদান সংশ্লিষ্ট অ্যান্ড্রয়েড ক্লাসে এর বাইন্ডিং ইনজেকশন করার জন্য দায়ী।

পূর্ববর্তী উদাহরণগুলি হিল্ট মডিউলগুলিতে ActivityComponent ব্যবহার প্রদর্শন করেছে।

হিল্ট নিম্নলিখিত উপাদানগুলি প্রদান করে:

হিল্ট উপাদান জন্য ইনজেক্টর
SingletonComponent Application
ActivityRetainedComponent N/A
ViewModelComponent ViewModel
ActivityComponent Activity
FragmentComponent Fragment
ViewComponent View
ViewWithFragmentComponent @WithFragmentBindings এর সাথে টীকাযুক্ত View
ServiceComponent Service

উপাদান জীবনকাল

হিল্ট স্বয়ংক্রিয়ভাবে সংশ্লিষ্ট অ্যান্ড্রয়েড ক্লাসের জীবনচক্র অনুসরণ করে জেনারেট হওয়া কম্পোনেন্ট ক্লাসের উদাহরণ তৈরি করে এবং ধ্বংস করে।

উত্পন্ন উপাদান এ তৈরি করা হয়েছে এ ধ্বংস করা হয়
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()

উপাদান স্কোপ

ডিফল্টরূপে, হিল্টের সমস্ত বাঁধাই অস্কোপড । এর মানে হল যে প্রতিবার আপনার অ্যাপ বাইন্ডিংয়ের অনুরোধ করে, হিল্ট প্রয়োজনীয় ধরনের একটি নতুন উদাহরণ তৈরি করে।

উদাহরণে, প্রতিবার হিল্ট AnalyticsAdapter প্রদান করে অন্য ধরণের উপর নির্ভরতা হিসাবে বা ফিল্ড ইনজেকশনের মাধ্যমে (যেমন ExampleActivity হিসাবে), Hilt AnalyticsAdapter এর একটি নতুন উদাহরণ প্রদান করে।

যাইহোক, হিল্ট একটি নির্দিষ্ট উপাদানের জন্য একটি বাঁধাইকে স্কোপ করার অনুমতি দেয়। বাইন্ডিং যে কম্পোনেন্টে স্কোপ করা হয়েছে তার জন্য হিল্ট শুধুমাত্র একবার একটি স্কোপড বাইন্ডিং তৈরি করে এবং সেই বাইন্ডিংয়ের জন্য সমস্ত অনুরোধ একই উদাহরণ ভাগ করে।

নীচের সারণী প্রতিটি উত্পন্ন উপাদানের জন্য সুযোগ টীকা তালিকাভুক্ত করে:

অ্যান্ড্রয়েড ক্লাস উত্পন্ন উপাদান ব্যাপ্তি
Application SingletonComponent @Singleton
Activity ActivityRetainedComponent @ActivityRetainedScoped
ViewModel ViewModelComponent @ViewModelScoped
Activity ActivityComponent @ActivityScoped
Fragment FragmentComponent @FragmentScoped
View ViewComponent @ViewScoped
@WithFragmentBindings এর সাথে টীকাযুক্ত View ViewWithFragmentComponent @ViewScoped
Service ServiceComponent @ServiceScoped

উদাহরণে, যদি আপনি @ActivityScoped ব্যবহার করে ActivityComponent কম্পোনেন্টে AnalyticsAdapter স্কোপ করেন, হিল্ট সংশ্লিষ্ট অ্যাক্টিভিটির সারাজীবনে AnalyticsAdapter একই উদাহরণ প্রদান করে:

কোটলিন

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

জাভা

@ActivityScoped
public class AnalyticsAdapter {

  private final AnalyticsService service;

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

ধরুন যে AnalyticsService একটি অভ্যন্তরীণ অবস্থা রয়েছে যার জন্য প্রতিবার একই দৃষ্টান্ত ব্যবহার করতে হবে—কেবল ExampleActivity তে নয়, অ্যাপের যেকোনো জায়গায়। এই ক্ষেত্রে, SingletonComponentAnalyticsService স্কোপ করা উপযুক্ত। ফলাফল হল যে যখনই উপাদানটিকে AnalyticsService এর একটি উদাহরণ প্রদান করার প্রয়োজন হয়, এটি প্রতিবার একই উদাহরণ প্রদান করে।

নিম্নলিখিত উদাহরণটি দেখায় কিভাবে একটি হিল্ট মডিউলে একটি উপাদানের সাথে বাঁধাই করার সুযোগ দেওয়া যায়। একটি বাইন্ডিং এর সুযোগ অবশ্যই উপাদানটির সুযোগের সাথে মিলবে যেখানে এটি ইনস্টল করা হয়েছে, তাই এই উদাহরণে আপনাকে ActivityComponent এর পরিবর্তে SingletonComponentAnalyticsService ইনস্টল করতে হবে:

কোটলিন

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

জাভা

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

হিল্ট কম্পোনেন্ট স্কোপ সম্পর্কে আরও জানতে, অ্যান্ড্রয়েড এবং হিল্টে স্কোপিং দেখুন।

উপাদান অনুক্রম

একটি কম্পোনেন্টে একটি মডিউল ইনস্টল করলে সেটির বাইন্ডিংগুলিকে সেই কম্পোনেন্টের অন্যান্য বাইন্ডিংয়ের নির্ভরতা হিসাবে অ্যাক্সেস করা যায় বা কম্পোনেন্ট হায়ারার্কিতে এটির নীচে থাকা যেকোনো চাইল্ড কম্পোনেন্টে:

ViewWithFragmentComponent FragmentComponent-এর অধীনে রয়েছে। ফ্র্যাগমেন্ট কম্পোনেন্ট     এবং ভিউ কম্পোনেন্ট অ্যাক্টিভিটি কম্পোনেন্টের অধীনে। কার্যকলাপ উপাদান অধীনে আছে     Activity Retained Component. ViewModel Component অধীনে আছে     Activity Retained Component. Activity Retained Component এবং Service Component     সিঙ্গেলটন কম্পোনেন্টের অধীনে রয়েছে।
চিত্র 1. হিল্ট তৈরি করে এমন উপাদানগুলির শ্রেণিবিন্যাস।

কম্পোনেন্ট ডিফল্ট বাইন্ডিং

প্রতিটি হিল্ট কম্পোনেন্ট ডিফল্ট বাইন্ডিংয়ের একটি সেট নিয়ে আসে যা হিল্ট আপনার নিজস্ব কাস্টম বাইন্ডিংগুলিতে নির্ভরতা হিসাবে ইনজেক্ট করতে পারে। মনে রাখবেন যে এই বাইন্ডিংগুলি সাধারণ কার্যকলাপ এবং খণ্ডের প্রকারের সাথে সামঞ্জস্যপূর্ণ এবং কোন নির্দিষ্ট উপশ্রেণীর সাথে নয়। এর কারণ হল হিল্ট সমস্ত ক্রিয়াকলাপ ইনজেক্ট করার জন্য একটি একক কার্যকলাপ উপাদান সংজ্ঞা ব্যবহার করে। প্রতিটি কার্যকলাপ এই উপাদান একটি ভিন্ন উদাহরণ আছে.

অ্যান্ড্রয়েড উপাদান ডিফল্ট বাঁধাই
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 ব্যবহার করেও উপলব্ধ। যেমন:

কোটলিন

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

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

জাভা

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 ব্যবহার করেও পাওয়া যায়। যেমন:

কোটলিন

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

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

জাভা

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

হিল্ট দ্বারা সমর্থিত নয় এমন ক্লাসে নির্ভরতা ইনজেক্ট করুন

হিল্ট সবচেয়ে সাধারণ অ্যান্ড্রয়েড ক্লাসগুলির জন্য সমর্থন সহ আসে। যাইহোক, হিল্ট সমর্থন করে না এমন ক্লাসে আপনাকে ফিল্ড ইনজেকশন করতে হতে পারে।

এই ক্ষেত্রে, আপনি @EntryPoint টীকা ব্যবহার করে একটি এন্ট্রি পয়েন্ট তৈরি করতে পারেন। একটি এন্ট্রি পয়েন্ট হল কোডের মধ্যে সীমানা যা হিল্ট দ্বারা পরিচালিত হয় এবং কোডটি নয়। এটি সেই বিন্দু যেখানে কোড প্রথমে হিল্ট পরিচালনা করে এমন বস্তুর গ্রাফে প্রবেশ করে। এন্ট্রি পয়েন্টগুলি হিল্টকে কোড ব্যবহার করার অনুমতি দেয় যা হিল্ট নির্ভরতা গ্রাফের মধ্যে নির্ভরতা প্রদান করতে পরিচালনা করে না।

উদাহরণস্বরূপ, হিল্ট সরাসরি সামগ্রী প্রদানকারীদের সমর্থন করে না। আপনি যদি চান যে কোনো বিষয়বস্তু প্রদানকারী কিছু নির্ভরতা পেতে হিল্ট ব্যবহার করুক, তাহলে আপনাকে এমন একটি ইন্টারফেস নির্ধারণ করতে হবে যা @EntryPoint সাথে টীকাযুক্ত প্রতিটি বাইন্ডিং টাইপের জন্য যা আপনি চান এবং কোয়ালিফায়ার অন্তর্ভুক্ত করুন। তারপরে নিম্নরূপ এন্ট্রি পয়েন্টটি ইনস্টল করার উপাদানটি নির্দিষ্ট করতে @InstallIn যোগ করুন:

কোটলিন

class ExampleContentProvider : ContentProvider() {

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

  ...
}

জাভা

public class ExampleContentProvider extends ContentProvider {

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

একটি এন্ট্রি পয়েন্ট অ্যাক্সেস করতে, EntryPointAccessors থেকে উপযুক্ত স্ট্যাটিক পদ্ধতি ব্যবহার করুন। প্যারামিটারটি কম্পোনেন্ট ইনস্ট্যান্স বা @AndroidEntryPoint অবজেক্ট হওয়া উচিত যা কম্পোনেন্ট হোল্ডার হিসেবে কাজ করে। নিশ্চিত করুন যে আপনি প্যারামিটার হিসাবে যে কম্পোনেন্টটি পাস করেন এবং EntryPointAccessors স্ট্যাটিক পদ্ধতি উভয়ই @EntryPoint ইন্টারফেসে @InstallIn টীকাতে Android ক্লাসের সাথে মেলে:

কোটলিন

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

জাভা

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 ব্যবহার করবেন।

হিল্ট এবং ড্যাগার

হিল্টটি ড্যাগার নির্ভরতা ইনজেকশন লাইব্রেরির উপরে তৈরি করা হয়েছে, যা একটি অ্যান্ড্রয়েড অ্যাপ্লিকেশনে ড্যাগারকে অন্তর্ভুক্ত করার একটি আদর্শ উপায় প্রদান করে।

ড্যাগারের ক্ষেত্রে, হিল্টের লক্ষ্যগুলি নিম্নরূপ:

  • অ্যান্ড্রয়েড অ্যাপের জন্য ড্যাগার-সম্পর্কিত পরিকাঠামো সহজ করতে।
  • অ্যাপগুলির মধ্যে সেটআপ, পঠনযোগ্যতা এবং কোড ভাগ করা সহজ করতে উপাদানগুলির একটি মানক সেট এবং সুযোগ তৈরি করতে৷
  • টেস্টিং, ডিবাগ বা রিলিজের মতো বিভিন্ন বিল্ড টাইপের বিভিন্ন বাইন্ডিং প্রভিশন করার একটি সহজ উপায় প্রদান করা।

কারণ অ্যান্ড্রয়েড অপারেটিং সিস্টেম তার নিজস্ব অনেকগুলি ফ্রেমওয়ার্ক ক্লাসকে ইনস্ট্যান্টিয়েট করে, একটি অ্যান্ড্রয়েড অ্যাপে ড্যাগার ব্যবহার করার জন্য আপনাকে যথেষ্ট পরিমাণে বয়লারপ্লেট লিখতে হবে। হিল্ট বয়লারপ্লেট কোড হ্রাস করে যা একটি অ্যান্ড্রয়েড অ্যাপ্লিকেশনে ড্যাগার ব্যবহারে জড়িত। হিল্ট স্বয়ংক্রিয়ভাবে তৈরি করে এবং নিম্নলিখিতগুলি সরবরাহ করে:

  • ড্যাগারের সাথে অ্যান্ড্রয়েড ফ্রেমওয়ার্ক ক্লাসগুলিকে একীভূত করার জন্য উপাদানগুলি যা আপনাকে অন্যথায় হাতে তৈরি করতে হবে৷
  • হিল্ট স্বয়ংক্রিয়ভাবে তৈরি করে এমন উপাদানগুলির সাথে ব্যবহার করার জন্য স্কোপ টীকা
  • Application বা Activity মতো অ্যান্ড্রয়েড ক্লাসগুলিকে উপস্থাপন করার জন্য পূর্বনির্ধারিত বাইন্ডিং
  • @ApplicationContext এবং @ActivityContext প্রতিনিধিত্ব করার জন্য পূর্বনির্ধারিত কোয়ালিফায়ার

ড্যাগার এবং হিল্ট কোড একই কোডবেসে সহাবস্থান করতে পারে। যাইহোক, বেশিরভাগ ক্ষেত্রে আপনার Android এ Dagger এর সমস্ত ব্যবহার পরিচালনা করতে Hilt ব্যবহার করা ভাল। হিল্টে ড্যাগার ব্যবহার করে এমন একটি প্রকল্প স্থানান্তর করতে, মাইগ্রেশন গাইড এবং হিল্ট কোডল্যাবে আপনার ড্যাগার অ্যাপ স্থানান্তরিত করা দেখুন।

অতিরিক্ত সম্পদ

হিল্ট সম্পর্কে আরও জানতে, নিম্নলিখিত অতিরিক্ত সংস্থানগুলি দেখুন।

নমুনা

কোডল্যাব

ব্লগ