تزریق وابستگی با استفاده از 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

 

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

جدیدترین ویدئوهای آموزشی

در بخش TV باگتو، آموزش های کوتاه و جدید را مشاهده نمایید

0 نظرات

برای ارسال نظر باید وارد حساب کاربری خود شوید
ورود به حساب کاربری ثبت نام

بیش از 50% تخفیف به مناسبت جمعه سیاه
فقط تا پایان امروز