تزریق وابستگی با استفاده از dagger2 در معماری mvvm با زبان کاتلین اندروید

تزریق وابستگی با استفاده از dagger2 در معماری mvvm  با زبان کاتلین اندروید
فهرست مقاله [نمایش]

    تزریق وابستگی چیست؟

    تزریق وابستگی مبتنی بر مفهومی به نام وارونگی کنترل (Inversion of Control) است. این مفهوم به این معنی است که یک کلاس باید وابستگی های خود را از کلاس خارجی دریافت کند نه اینکه آنها را در کلاس فرا خوانی کند.

    تزریق وابستگی در Android با استفاده از Dagger2

    Dagger2 یک framework تزریق وابستگی کاملاً استاتیک و کامپایل شده است که بر اساس درخواست مشخصات جاوا 330(JSR) مورد استفاده برای اندروید و جاوا است. از کد generation استفاده می کند و مبتنی بر annotation نویسی است. کدی که تولید شده برای خواندن و debug بسیار آسان است. نسخه قبلی daggerتوسط کمپانی Square ایجاد شد و اکنون توسط گوگل نگهداری و توسعه داده میشود.

    سه قسمت اصلی dagger که با آنها آشنا میشیم:

    1) Dependency Provider 

    Dependency Consumer (2

    Component (3

     

    1- Dependency Provider

    object هایی که dependencies نامیده می شوند را فراهم می کند. کلاسی که وظیفه تأمین وابستگی را بر عهده دارد،با annotation(انوتیشن) Module و متد هایی که وابستگی (object) ها را در این کلاس ایجاد می کند با انوتیشن provides مشخص میشود

    2-Dependency Consumer

    كلاسی است كه در آن ما باید object ها را معرفی كنیم. اما نیازی نیست که آن را با کلمه کلیدی جدید معرفی کنیم. حتی لازم نیست که به عنوان یک argument به آن برسید. اما dagger وابستگی را فراهم می کند و برای این کار فقط باید تعریف object را با انوتیشن Inject@ بنویسیم.

    3. Component

    یک interface که به عنوان واسط بینdependency consumer و dependency provider است و با انوتیشن Component@ مشخص میشود.

    Dependencyهای dagger2

    در فایل build.gradle پروژه dependency های زیر را وارد کنید

        ext.dagger2_version = '2.24'
    // Basic Dagger 2 (required)
        implementation "com.google.dagger:dagger:$dagger2_version"
        kapt "com.google.dagger:dagger-compiler:$dagger2_version"
    // dagger.android package (optional)
        implementation "com.google.dagger:dagger-android:$dagger2_version"
        kapt "com.google.dagger:dagger-android-processor:$dagger2_version"
    // Support library support (optional)
        kapt "com.google.dagger:dagger-android-support:$dagger2_version"
    
    

    Dependencyهای Retrofit

    implementation 'com.squareup.retrofit2:retrofit:2.6.1'
    implementation 'com.squareup.retrofit2:retrofit-converters:2.6.1'
    implementation 'com.squareup.retrofit2:retrofit-adapters:2.6.1'
    implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
    
    

    یک کلاس به نام APIModule می سازیم که کلاس provider ما هست و کدهای آن به صورت زیر است

    
    class APIModule constructor(baseURL:String) {
        var baseURL:String?=""
    
        init {
            this.baseURL = baseURL
        }
    @Singleton
    @Provides
     fun provideOKHttpClient():OkHttpClient{
         return  OkHttpClient.Builder()
             .readTimeout(1200,TimeUnit.SECONDS)
             .connectTimeout(1200,TimeUnit.SECONDS)
             .build()
    
     }
    @Singleton
    @Provides
    fun provideGSON(): GsonConverterFactory {
    
       return  GsonConverterFactory.create()
    
        }
    @Singleton
     @Provides
     fun provideRetrofit(gsonConverterFactory: GsonConverterFactory,okHttpClient: OkHttpClient):Retrofit{
    
          return     Retrofit.Builder()
                    .baseUrl(baseURL)
                    .addConverterFactory(gsonConverterFactory)
                    .client(okHttpClient)
                     .build()
     }
    
        @Provides
        fun provideRetroRepository():RetrofitRepository{
            return RetrofitRepository()
        }
    
    }
    
    
    
    
    
    
    

    یک interface میسازیم و اسمش را APIComponent میگذاریم در پایین کدهایش را می بینید.

    @Singleton
    @Component(modules = [AppModule::class,APIModule::class])
    interface APIComponent {
        fun inject(retrofitRepository: RetrofitRepository)
        fun inject(retroViewModel: RetroViewModel)
        fun inject(retroFragment: RetroFragment)
        fun inject(retroViewModelFactory:RetroViewModelFactory)
    }
    
    

    در خط دوم گفتیم که این component از چه modules های استفاده کند.

    DaggerComponent Initialization

    DaggerComponent را در کلاس Application تعریف و Initiate کنید تا در سراسر برنامه در دسترس باشد. در کلاس application متد زیر را بنویسید

    fun initDaggerComponent():APIComponent{
        apiComponent =   DaggerAPIComponent
            .builder()
            .aPIModule(APIModule(APIURL.BASE_URL))
            .build()
        return  apiComponent
    
    }
    

    Dependency Consumer

    RetroRepository کلاسی است که با استفاده از انوتیشن Inject،تزریق وابستگی را انجام میدهد.

    @Inject
    lateinit var retrofit: Retrofit
    

    کد های کلاس RetroRepository به صورت زیر می باشد:

    class  RetrofitRepository {
        lateinit var apiComponent: APIComponent
        var postInfoMutableList: MutableLiveData<List<PostInfo>> = MutableLiveData()
        @Inject
        lateinit var retrofit: Retrofit
        init {
           /* apiComponent =   DaggerAPIComponent
                .builder()
                .aPIModule(APIModule(APIURL.BASE_URL))
                .build()
            apiComponent.inject(this)*/
    
            var apiComponent :APIComponent =  MyRetroApplication.apiComponent
            apiComponent.inject(this)
        }
    
    
        fun fetchPostInfoList(): LiveData<List<PostInfo>> {
    
             var apiService:APIService = retrofit.create(APIService::class.java)
             var postListInfo : Call<List<PostInfo>> =  apiService.makeRequest()
            postListInfo.enqueue(object :Callback<List<PostInfo>>{
                override fun onFailure(call: Call<List<PostInfo>>, t: Throwable) {
                 Log.d("RetroRepository","Failed:::"+t.message)
                }
    
                override fun onResponse(call: Call<List<PostInfo>>, response: Response<List<PostInfo>>) {
                    var postInfoList = response.body()
                    postInfoMutableList.value = postInfoList
    
                }
            })
    
             return  postInfoMutableList
    
        }
    
    
    }
    

    کلاس ViewModelFactory

    برای انتقال آرگومانها به ViewModel از کلاس view model factory استفاده میکنیم. در این برنامه RetroRepository در ViewModelProvider تزریق می شود و به عنوان آرگومان به ViewModel ارسال می شود.

    class RetroViewModelFactory : ViewModelProvider.Factory {
        lateinit var apiComponent: APIComponent
        @Inject
        lateinit var retrofitRepository: RetrofitRepository
    
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
         //   initDaggerComponent()
           var apiComponent :APIComponent =  MyRetroApplication.apiComponent
            apiComponent.inject(this)
            if (modelClass.isAssignableFrom(RetroViewModel::class.java)) {
                return RetroViewModel(retrofitRepository) as T
            }
            throw IllegalArgumentException("Unknown ViewModel class")
        }
    {
    
    

    کلاس RetroViewModel

    RetrofitRepository به عنوان آرگومان وبدونه این که object از آن بسازیم منتقل می شود.

    class RetroViewModel(retrofitRepository: RetrofitRepository): ViewModel() {
    
        lateinit var retrofitRepository:RetrofitRepository
        var postInfoLiveData: LiveData<List<PostInfo>> = MutableLiveData()
    
        init {
            this.retrofitRepository  = retrofitRepository
            fetchPostInfoFromRepository()
            }
    
        fun fetchPostInfoFromRepository(){
            postInfoLiveData =  retrofitRepository.fetchPostInfoList()
        }
    
    
    

    کلاس APIURL آدرس api هارا از این کلاس میگیریم(BaseUrl)

    class APIURL {
        companion object {
            const val BASE_URL  = "https://jsonplaceholder.typicode.com/"
        }
    }
    
    

    کلاس Service Interface که یک interface است و حاوی api های مورد نیاز است

    interface APIService {
    
        @GET("posts")
        fun makeRequest(): Call<List<PostInfo>>
    }
    
    

    سورس این آموزش رو میتونید از لینک زیر دانلود کنید.

    https://github.com/maysambabaei/Dagger2-retrofit-mvvm-kotlin/tree/master

    سوالات و مشکلات خود را در بخش نظرات برای ما ارسال کنید.

    اطلاعات نویسنده
    • نویسنده: میثم بابائی

    ارسال دیدگاه

    برای افزودن دیدگاه خود، نیاز است ابتدا وارد حساب کاربری‌تان شوید


    دیدگاه کاربران