Dagger হল Java এবং Kotlin-এর জন্য একটি ডিপেন্ডেন্সি ইনজেকশন ফ্রেমওয়ার্ক যা অ্যানোটেশন প্রসেসিংয়ের মাধ্যমে কম্পাইল সময়ে DI কোড জেনারেট করে। Hilt হল Android-এর জন্য Dagger-এর উপরে একটি আচ্ছাদন যা কম্পোনেন্ট সেটআপ এবং জীবনচক্র ব্যবস্থাপনাকে সহজ করে। Google, 2025-এর মতে, Google Play Top-100 থেকে 70% এর বেশি Android অ্যাপে Hilt ব্যবহৃত হয়, যা পূর্বনির্ধারিত কম্পোনেন্টের মাধ্যমে Activity, Fragment, ViewModel এবং Service সমর্থন করে। উভয় ফ্রেমওয়ার্ক কম্পাইল-টাইম ডিপেন্ডেন্সি গ্রাফ যাচাইকরণ প্রদান করে, রানটাইম ইনজেকশন ত্রুটিগুলি দূর করে।
মূল বিষয়
Dagger হল একটি ডিপেন্ডেন্সি ইনজেকশন ফ্রেমওয়ার্ক যা কম্পাইল-টাইম কোড জেনারেশন সহ। মূলত Square-এ বিকশিত এবং পরে Google-এ হস্তান্তরিত, Dagger ডিপেন্ডেন্সি গ্রাফ বিশ্লেষণ এবং ফ্যাক্টরি ক্লাস জেনারেট করতে Java APT অ্যানোটেশন প্রসেসর ব্যবহার করে। রানটাইম-DI (Guice, Koin)-এর বিপরীতে, Dagger রিফ্লেকশন ব্যবহার করে না — সমস্ত কোড কম্পাইল সময়ে তৈরি হয়, যা রানটাইমে সর্বোচ্চ কর্মক্ষমতা এবং বিল্ড সময়ে ত্রুটি সনাক্তকরণ নিশ্চিত করে।
Hilt হল একটি Google লাইব্রেরি যা Dagger-এর উপরে তৈরি এবং Android-এর জন্য অপ্টিমাইজড। Hilt Android কম্পোনেন্ট জীবনচক্রের সাথে সঙ্গতিপূর্ণ পূর্বনির্ধারিত কম্পোনেন্ট প্রদান করে: Application-এর জন্য @SingletonComponent, Activity-র জন্য @ActivityComponent, Fragment-এর জন্য @FragmentComponent, ViewModel-এর জন্য @ViewModelComponent। এটি বিশুদ্ধ Dagger-এ প্রয়োজনীয় রুটিন Component এবং Module কনফিগারেশন দূর করে। Hilt @AndroidEntryPoint-এর মাধ্যমে প্রতিটি Android কম্পোনেন্টের জন্য স্বয়ংক্রিয়ভাবে ডিপেন্ডেন্সি গ্রাফও জেনারেট করে।
Google I/O 2024 অনুসারে, Kotlin-এ লেখা Android অ্যাপ্লিকেশনে DI-এর জন্য Hilt হল প্রস্তাবিত সমাধান। Jetpack লাইব্রেরিগুলির (Navigation, Room, WorkManager) @HiltViewModel এবং @HiltWorker-এর মাধ্যমে Hilt-এর সাথে অন্তর্নির্মিত সংহতকরণ রয়েছে। যে প্রকল্পগুলি Android ব্যবহার করে না (বিশুদ্ধ Java/Kotlin লাইব্রেরি, সার্ভার অ্যাপ্লিকেশন), সেখানে Hilt আচ্ছাদন ছাড়া বিশুদ্ধ Dagger ব্যবহার করা হয়।
DI ফ্রেমওয়ার্ক ছাড়া, ডেভেলপার কনস্ট্রাক্টর বা ফ্যাক্টরির মাধ্যমে ম্যানুয়ালি অবজেক্ট তৈরি করে, চেইন বরাবর ডিপেন্ডেন্সি পাস করে। প্রতিটি নতুন প্রয়োজনীয়তার অর্থ চেইনের সমস্ত কনস্ট্রাক্টরের সিগনেচার পরিবর্তন করা। Dagger এই প্রক্রিয়াটি স্বয়ংক্রিয় করে: আপনি কেবল ঘোষণা করেন কোন প্রকার প্রয়োজন (@Inject constructor), এবং Dagger সমস্ত নেস্টেড প্রকার সমাধান করে ডিপেন্ডেন্সি গ্রাফ তৈরি করে। যখন ডিপেন্ডেন্সি পরিবর্তিত হয়, Dagger স্বয়ংক্রিয়ভাবে জেনারেটেড কোড আপডেট করে — চেইনে ভুল করা অসম্ভব।
ডিপেন্ডেন্সি ইনজেকশন হল একটি প্যাটার্ন যেখানে একটি অবজেক্ট তার ডিপেন্ডেন্সিগুলি নিজে তৈরি না করে বাইরে থেকে গ্রহণ করে। DI নিয়ন্ত্রণের উলটো (IoC) নীতি বাস্তবায়ন করে: একটি ক্লাস তার নিজস্ব ডিপেন্ডেন্সি তৈরির জন্য দায়ী নয়, বরং কনস্ট্রাক্টর, পদ্ধতি বা ফিল্ডের মাধ্যমে সেগুলি ঘোষণা করে। কনস্ট্রাক্টর ইনজেকশন সবচেয়ে পছন্দনীয় কারণ এটি নিশ্চিত করে যে অবজেক্টটি বৈধ অবস্থায় তৈরি হয়েছে।
| ইনজেকশনের প্রকার | Dagger সিনট্যাক্স | কখন ব্যবহার করবেন |
|---|---|---|
| Constructor injection | @Inject constructor | প্রাথমিক পদ্ধতি — সমস্ত কাস্টম ক্লাসের জন্য |
| Field injection | @Inject lateinit var | শুধুমাত্র Android কম্পোনেন্টের জন্য (Activity, Fragment) |
| Method injection | @Inject fun bind() | পোস্ট-কনস্ট্রাক্ট ইনিশিয়ালাইজেশনের জন্য |
DI-এর প্রধান সুবিধাগুলির মধ্যে রয়েছে পরীক্ষণযোগ্যতা (ডিপেন্ডেন্সিগুলি mock অবজেক্ট দিয়ে প্রতিস্থাপন করা যায়), শিথিল সংযুক্তি (ক্লাসগুলি বাস্তবায়নের উপর নয়, ইন্টারফেসের উপর নির্ভর করে), এবং স্কোপের মাধ্যমে বস্তুর জীবনচক্রের স্পষ্ট ব্যবস্থাপনা। Dagger স্বয়ংক্রিয়ভাবে গ্যারান্টি দেয় যে একটি অবজেক্ট তার স্কোপের মধ্যে একবার তৈরি হয় এবং স্কোপ থেকে বের হলে ধ্বংস হয়।
Component হল Dagger ডিপেন্ডেন্সি গ্রাফের কেন্দ্রীয় উপাদান। এটি @Component দিয়ে অ্যানোটেটেড একটি ইন্টারফেস যা Module এবং ইনজেকশন লক্ষ্যগুলির মধ্যে সেতু বর্ণনা করে। Dagger কম্পাইল সময়ে Component বাস্তবায়ন (যেমন DaggerAppComponent) জেনারেট করে। Component নির্ধারণ করে যে প্রয়োজনীয় প্রকার ফেরত দেওয়ার বিমূর্ত পদ্ধতি বা ফিল্ড ইনজেকশনের জন্য অবজেক্ট গ্রহণকারী inject পদ্ধতির মাধ্যমে কোন প্রকারগুলি ইনজেকশনের জন্য উপলব্ধ।
// Module: Dagger নিজে তৈরি করতে পারে না এমন ডিপেন্ডেন্সি প্রদান করে
@Module
class NetworkModule {
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.build()
}
@Provides
@Singleton
fun provideApiService(client: OkHttpClient): ApiService {
return Retrofit.Builder()
.baseUrl("https://api.example.com/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
}
}
// Component: Module এবং Injection লক্ষ্যগুলিকে সংযুক্ত করে
@Component(modules = [NetworkModule::class])
interface AppComponent {
fun inject(activity: MainActivity)
fun getApiService(): ApiService
}
@Module হল একটি ক্লাস যাতে @Provides সহ পদ্ধতি থাকে যা ডিপেন্ডেন্সির ইনস্ট্যান্স ফেরত দেয়। Module সেই প্রকারগুলির জন্য ব্যবহৃত হয় যা Dagger স্বয়ংক্রিয়ভাবে তৈরি করতে পারে না: তৃতীয়-পক্ষের লাইব্রেরি (OkHttp, Retrofit), কনস্ট্রাক্টর প্যারামিটার সহ অবজেক্ট, বাস্তবায়ন নির্বাচন সহ ইন্টারফেস। @Binds হল @Provides-এর একটি বিকল্প যখন একটি পদ্ধতি ইন্টারফেস ফেরত দেয় এবং একটি একক বাস্তবায়ন গ্রহণ করে: Dagger পদ্ধতি কল না করেই সরাসরি কাস্ট জেনারেট করে।
@Scope ডিপেন্ডেন্সি গ্রাফে একটি বস্তুর জীবনকাল নির্ধারণ করে। @Singleton — বস্তুটি পুরো অ্যাপ্লিকেশনের জন্য একবার তৈরি হয়। @ActivityScoped — বস্তুটি ততক্ষণ বেঁচে থাকে যতক্ষণ Activity বেঁচে থাকে। @FragmentScoped — যতক্ষণ Fragment বেঁচে থাকে। স্কোপ ছাড়া, Dagger প্রতিটি ইনজেকশনে একটি নতুন ইনস্ট্যান্স তৈরি করে। @Reusable — সেই বস্তুগুলির জন্য একটি স্কোপ যেগুলি সিঙ্গলটন হতে হবে না কিন্তু তৈরি করা ব্যয়বহুল — Dagger ইনস্ট্যান্স ক্যাশ করতে পারে তবে এটি গ্যারান্টি দেয় না।
Hilt পূর্বনির্ধারিত কম্পোনেন্ট এবং স্বয়ংক্রিয় বেস গ্রাফ জেনারেশনের মাধ্যমে Android-এর জন্য Dagger কনফিগারেশন সহজ করে। Application ক্লাসে @HiltAndroidApp অ্যানোটেশন Hilt কম্পোনেন্ট জেনারেশন ট্রিগার করে। এই অ্যানোটেশন ছাড়া, Hilt কাজ করে না — এটি Hilt ব্যবহার করে যেকোনো Android অ্যাপ্লিকেশনের জন্য বাধ্যতামূলক। @HiltAndroidApp পিতৃ SingletonComponent তৈরি করে, যেখান থেকে অ্যাপ্লিকেশনের অন্যান্য সমস্ত কম্পোনেন্ট উত্তরাধিকার সূত্রে প্রাপ্ত হয়।
@HiltAndroidApp
class MyApplication : Application()
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject lateinit var apiService: ApiService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// apiScope ইতিমধ্যে onCreate কলের আগে ইনজেক্ট করা হয়েছে
}
}
@Module
@InstallIn(SingletonComponent::class)
class AppModule {
@Provides
@Singleton
fun provideDatabase(@ApplicationContext ctx: Context): AppDatabase {
return Room.databaseBuilder(ctx, AppDatabase::class.java, "app.db").build()
}
}
@AndroidEntryPoint হল Activity, Fragment, Service, BroadcastReceiver এবং View-এর জন্য একটি অ্যানোটেশন। এটি প্রতিটি প্রকারের জন্য একটি Hilt কম্পোনেন্ট জেনারেট করে: Activity-তে @AndroidEntryPoint একটি ActivityComponent তৈরি করে যা SingletonComponent থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয়। চাইল্ড কম্পোনেন্ট স্বয়ংক্রিয়ভাবে পিতৃর সমস্ত ডিপেন্ডেন্সি গ্রহণ করে। @Inject lateinit var সহ Field injection শুধুমাত্র @AndroidEntryPoint দিয়ে অ্যানোটেটেড ক্লাসে উপলব্ধ — সাধারণ ক্লাসে কনস্ট্রাক্টর ইনজেকশন ব্যবহার করা হয়।
@InstallIn নির্দিষ্ট করে কোন Hilt কম্পোনেন্টে একটি মডিউল ইনস্টল করা হয়েছে। @InstallIn(SingletonComponent::class) সহ NetworkModule পুরো অ্যাপ্লিকেশন জুড়ে উপলব্ধ। @InstallIn(ActivityComponent::class) সহ একটি Module শুধুমাত্র Activity-তে উপলব্ধ। এটি ডিপেন্ডেন্সি গ্রাফগুলিকে বিচ্ছিন্ন করে: Activity-নির্দিষ্ট মডিউলগুলি Fragment এবং ViewModel-এ দৃশ্যমান নয়, অবৈধ ডিপেন্ডেন্সির আকস্মিক ব্যবহার প্রতিরোধ করে। @ApplicationContext হল অ্যাপ্লিকেশন Context পাওয়ার জন্য Hilt-এর অন্তর্নির্মিত কোয়ালিফায়ার।
যখন একই ইন্টারফেসের দুটি ভিন্ন বাস্তবায়ন ইনজেক্ট করার প্রয়োজন হয়, তখন কোয়ালিফায়ার ব্যবহার করা হয়। Hilt স্ট্রিং শনাক্তকারীর জন্য @Named এবং @Qualifier সহ কাস্টম অ্যানোটেশন সমর্থন করে। উদাহরণস্বরূপ, বিভিন্ন স্ট্রিং কনফিগারেশনের জন্য @Named("baseUrl") এবং @Named("imageBaseUrl")। কাস্টম কোয়ালিফায়ারগুলি কম্পাইল-টাইম যাচাইয়ের কারণে @Named-এর চেয়ে ভাল — ভুল স্ট্রিং নাম রানটাইম পর্যন্ত সনাক্ত হবে না।
@HiltViewModel হল একটি অ্যানোটেশন যা ম্যানুয়াল ViewModelProvider.Factory-কে প্রতিস্থাপন করে। @HiltViewModel দিয়ে অ্যানোটেটেড এবং @Inject constructor সহ একটি ক্লাস স্বয়ংক্রিয়ভাবে Dagger-এর মাধ্যমে সমস্ত ডিপেন্ডেন্সি গ্রহণ করে। Hilt Jetpack ViewModelProvider দ্বারা ব্যবহৃত একটি ViewModelFactory জেনারেট করে। Hilt ছাড়া, ডেভেলপারকে Activity বা Fragment থেকে প্রতিটি প্যারামিটার পাস করে ম্যানুয়ালি ফ্যাক্টরি লিখতে হয়।
@HiltViewModel
class MainViewModel
@Inject constructor(
private val apiService: ApiService,
private val database: AppDatabase
) : ViewModel() {
private val _users = MutableStateFlow<List<User>>(emptyList())
val users: StateFlow<List<User>> = _users.asStateFlow()
fun loadUsers() {
viewModelScope.launch {
_users.value = apiService.getUsers()
}
}
}
// Activity-তে — Hilt স্বয়ংক্রিয়ভাবে ViewModel তৈরি করে
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val viewModel: MainViewModel by viewModels()
}
ViewModelScoped হল ডিপেন্ডেন্সির জন্য Hilt-এর একটি স্কোপ যা ততক্ষণ বেঁচে থাকে যতক্ষণ ViewModel বেঁচে থাকে। যদি একই প্রকারের দুটি ViewModel একই @ViewModelScoped ডিপেন্ডেন্সি ইনজেক্ট করে, প্রতিটি নিজস্ব ইনস্ট্যান্স পায়। এটি @ViewModelScoped-কে @ActivityScoped থেকে আলাদা করে, যেখানে একটি Activity সমস্ত ফ্রাগমেন্টের জন্য একটি ইনস্ট্যান্স পায়। ViewModel-নির্দিষ্ট ডিপেন্ডেন্সির (যেমন SavedStateHandle) জন্য, @HiltViewModel ব্যবহার করা হয় @Inject constructor(savedStateHandle: SavedStateHandle) সহ।
Hilt Hilt Extensions লাইব্রেরির মাধ্যমে assisted injection সমর্থন করে। Assisted injection ইনজেকশনের সময় কনস্ট্রাক্টরে প্যারামিটার পাস করার অনুমতি দেয় যখন কিছু ডিপেন্ডেন্সি শুধুমাত্র রানটাইমে জানা যায় (উদাহরণস্বরূপ, একটি ইন্টেন্ট থেকে ব্যবহারকারী ID)। Assisted injection-এর জন্য @AssistedInject ব্যবহার করা হয় @Assisted প্যারামিটারের সংমিশ্রণে। Hilt একটি AssistedFactory জেনারেট করে যা মানক পদ্ধতিতে ইনজেক্ট করা যেতে পারে।
বিশুদ্ধ Dagger-এর জন্য Component-এর ম্যানুয়াল তৈরি, স্কোপ নির্ধারণ এবং প্রতিটি Android কম্পোনেন্টে ইনজেকশন কনফিগারেশন প্রয়োজন। ডেভেলপার AppComponent, ActivityComponent, FragmentComponent তৈরি করে এবং @Subcomponent-এর মাধ্যমে তাদের সম্পর্ক পরিচালনা করে। এই পদ্ধতি সর্বোচ্চ নিয়ন্ত্রণ দেয় তবে উল্লেখযোগ্য boilerplate কোড প্রয়োজন। Dagger বড় প্রকল্পে ব্যবহৃত হয় যেখানে অ-মানক DI আর্কিটেকচার প্রয়োজন, বা অ-Android Java/Kotlin প্রকল্পে।
Hilt boilerplate স্বয়ংক্রিয় করে: একটি @HiltAndroidApp, প্রতিটি কম্পোনেন্টের জন্য একটি @AndroidEntryPoint, পূর্বনির্ধারিত স্কোপ। Google সমস্ত নতুন Android প্রকল্পের জন্য Hilt সুপারিশ করে। Dagger থেকে Hilt-এ মাইগ্রেশনে Component-কে @InstallIn দিয়ে প্রতিস্থাপন করা, @Subcomponent-কে পূর্বনির্ধারিত Hilt কম্পোনেন্ট দিয়ে প্রতিস্থাপন করা এবং ম্যানুয়াল ViewModelProvider.Factory-কে @HiltViewModel দিয়ে প্রতিস্থাপন করা অন্তর্ভুক্ত। বেশিরভাগ @Module ক্লাস @Provides পদ্ধতি পরিবর্তন না করে @InstallIn যোগ করে মাইগ্রেট করা হয়।
| বৈশিষ্ট্য | Dagger | Hilt |
|---|---|---|
| সেটআপ | ম্যানুয়াল: Component, Subcomponent, Builder | স্বয়ংক্রিয়: @HiltAndroidApp, @AndroidEntryPoint |
| Android কম্পোনেন্ট | কোনো পূর্বনির্ধারিত নেই | 12+ অন্তর্নির্মিত কম্পোনেন্ট |
| ViewModel | ম্যানুয়াল ফ্যাক্টরি | @HiltViewModel + @Inject constructor |
| মাল্টিমডিউল | @Component(dependencies)-এর মাধ্যমে | @InstallIn + একত্রীকরণের মাধ্যমে |
| জটিলতা | উচ্চ — অভিজ্ঞতা প্রয়োজন | নিম্ন — স্বজ্ঞাতভাবে বোধগম্য |
| নমনীয়তা | সর্বোচ্চ | মানক (95% পরিস্থিতি কভার করে) |
Hilt-এর সীমাবদ্ধতা: লাইব্রেরি শুধুমাত্র Android সমর্থন করে (বিশুদ্ধ সার্ভার-সাইড Java প্রকল্পের জন্য উপযুক্ত নয়), একটি নির্দিষ্ট কম্পোনেন্ট কাঠামো আরোপ করে (ওভাররাইড করা কঠিন), এবং Jetpack Compose প্রকল্পের জন্য android.hilt:hilt-navigation-compose-এর উপর নির্ভরতা যোগ করে। Compose অ্যাপ্লিকেশনের জন্য, Hilt @HiltViewModel প্রদান করে যা Composable-এ hiltViewModel()-এর মাধ্যমে অ্যাক্সেসযোগ্য — Activity থেকে ম্যানুয়াল ViewModel সরবরাহ ছাড়া।
সচরাচর জিজ্ঞাসিত প্রশ্ন
Dagger হল ম্যানুয়াল Component এবং Module কনফিগারেশন সহ একটি মৌলিক কম্পাইল-টাইম DI ফ্রেমওয়ার্ক। Hilt হল Android-এর জন্য একটি আচ্ছাদন যা কম্পোনেন্ট তৈরি এবং Activity, Fragment, ViewModel, Service এবং BroadcastReceiver-এর জীবনচক্রের সাথে সংহতকরণ স্বয়ংক্রিয় করে।
@HiltAndroidApp Application-এর জন্য Hilt কম্পোনেন্ট জেনারেশন সক্ষম করে। এই অ্যানোটেশন ছাড়া, Hilt মৌলিক SingletonComponent তৈরি করতে পারে না যেখান থেকে সমস্ত ActivityComponent, FragmentComponent এবং ViewModelComponent উত্তরাধিকার সূত্রে প্রাপ্ত হয়। অ্যানোটেশন যেকোনো Hilt প্রকল্পের জন্য বাধ্যতামূলক।
Hilt Navigation NavBackStackEntry-তে ViewModel-এর জন্য @HiltViewModel এবং নেভিগেশন গ্রাফের মধ্যে ViewModel স্কোপ করার জন্য hiltNavGraphViewModels() প্রদান করে। android.hilt:hilt-navigation-fragment লাইব্রেরি প্রতিটি NavBackStackEntry-এর জন্য স্বয়ংক্রিয়ভাবে একটি ViewModel তৈরি করে।
অ্যাপ্লিকেশন Context-এর জন্য @ApplicationContext বা Activity Context-এর জন্য @ActivityContext ব্যবহার করুন। Hilt android.hilt:hilt-android লাইব্রেরিতে এই কোয়ালিফায়ারগুলি অন্তর্নির্মিত প্রদান করে। @ActivityContext শুধুমাত্র ActivityComponent-এ ইনস্টল করা মডিউলগুলিতে উপলব্ধ।
@Binds হল @Provides-এর একটি কার্যকর বিকল্প যখন একটি পদ্ধতি ঠিক একটি প্যারামিটার গ্রহণ করে এবং তার প্রকারকে ইন্টারফেস হিসাবে ফেরত দেয়। @Binds পদ্ধতি কল না করেই সরাসরি কাস্ট জেনারেট করে, জেনারেটেড কোডের পরিমাণ হ্রাস করে এবং ইনজেকশন কর্মক্ষমতা উন্নত করে।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন