استفاده از Dagger hilt به صورت پروژه محور (قسمت سوم)

قسمت های قبلی: https://vrgl.ir/ez4b2 https://vrgl.ir/u5BLy در قسمت دوم، یک ماژول تعریف کردیم که قراره داخل این قسمت، وابستگی هارو بهش اضافه کنیم.برای شروع، بیس یو ار ال ها رو تامین می کنیم:@Provides @Singleton fun provideIceAndFireBaseURL(): String = &quothttps://www.anapioficeandfire.com/&quot @Provides @Singleton fun provideQuotesBaseURL(): String = &quothttps://got-quotes.herokuapp.com/&quotخب الان ی مشکلی پیش میاد ? چون که از ما از دو وب سرویس متفاوت استفاده می کنیم و اینکه هر دو تامین کننده، ی نوع داده رو بازگشت میدن و باید به دگر بفمهمونیم که کجا از کدوم بیس یو ار ال استفاده کنه! اینجاست که ما از Qualifier استفاده می کنیم.در پوشه di-> annotation یک فایل به نام Annotations ایجاد می کنیم:@Qualifier @Retention(AnnotationRetention.BINARY) annotation class IceAndFire @Qualifier @Retention(AnnotationRetention.BINARY) annotation class Quotesحالا انوتیشن IceAndFire و Quotes رو به بیس یو ار ال های خودمون اضافه می کنیم:@IceAndFire @Provides @Singleton fun provideIceAndFireBaseURL(): String = &quothttps://www.anapioficeandfire.com/&quot @Quotes @Provides @Singleton fun provideQuotesBaseURL(): String = &quothttps://got-quotes.herokuapp.com/&quotبرای مکانیزم کش و کلاینت کاستوم شده okHttp، به کلاس NetworkHelper نیاز داریم، و کلاس NetworkHelper هم برای کار، به Context نیاز داره! به این صورت تعریفش می کنیم:@Provides @Singleton fun provideNetworkHelper(@ApplicationContext context: Context): NetworkHelper = NetworkHelper(context)از انوتیشن ApplicationContext برای تزریق Context به NetworkHelper استفاده می کنیم. حالا کلاینت OkHttp رو تعریف می کنیم:@Provides @Singleton fun provideOkHttpClient(@ApplicationContext context: Context, networkHelper: NetworkHelper): OkHttpClient { val cacheSize = (5 * 1024 * 1024).toLong() val myCache = Cache(context.cacheDir, cacheSize) return OkHttpClient.Builder() .cache(myCache) .addInterceptor { chain -> var request = chain.request() request = if (networkHelper.isNetworkConnected()) request.newBuilder().header(&quotCache-Control&quot, &quotpublic, max-age=&quot + 5).build() else request.newBuilder().header(&quotCache-Control&quot, &quotpublic, only-if-cached, max-stale=&quot + 60 * 60 * 24 * 7).build() chain.proceed(request) } .build() }دوباره برای تزریق Context از ApplicationContext استفاده می کنیم.حالا برای تامین Retrofit، چون دو بیس یو ار ال داریم، پس باید دو آبجکت از رتروفیت تعریف کنیم:@IceAndFire @Provides @Singleton fun provideIceAndFireRetrofit(client: OkHttpClient, @IceAndFire baseUrl: String): Retrofit { return Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .baseUrl(baseUrl) .client(client) .build() } @Quotes @Provides @Singleton fun provideQuotesRetrofit(client: OkHttpClient, @Quotes baseUrl: String): Retrofit { return Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .baseUrl(baseUrl) .client(client) .build() }در اینجا دوباره از انوتیشن IceAndFire و Quotes استفاده کردیم که به دگر بفهمونیم در کجا از کدومش استفاده می کنیم! اگه دقت کرده باشید برای پارامتر بیس یو ار ال در هر دو فانکشن، مشخص کردیم که کدوم بیس یو ار ال رو میخوایم.حالا نوبت میرسه به تامین کلاس های نتورک و ApiHelper های اپلیکیشنه:@Provides @Singleton fun provideIceAndFireApiService(@IceAndFire retrofit: Retrofit) = retrofit.create(IceAndFireApiService::class.java) @Provides @Singleton fun provideIceAndFireApiHelper(@Quotes retrofit: Retrofit) = retrofit.create(QuotesApiService::class.java) @Provides @Singleton fun provideQuotesApiService(apiImpl: IceAndFireApiImpl): IceAndFireApiHelper = apiImpl @Provides @Singleton fun provideQuotesApiHelper(apiImpl: QuotesApiImpl): QuotesApiHelper = apiImplخب، ماژول ما تموم شد و کد کامل شده:@Module @InstallIn(ApplicationComponent::class) class IceAndFireModule { @IceAndFire @Provides @Singleton fun provideIceAndFireBaseURL(): String = &quothttps://www.anapioficeandfire.com/&quot @Quotes @Provides @Singleton fun provideQuotesBaseURL(): String = &quothttps://got-quotes.herokuapp.com/&quot @Provides @Singleton fun provideNetworkHelper(@ApplicationContext context: Context): NetworkHelper = NetworkHelper(context) @Provides @Singleton fun provideOkHttpClient(@ApplicationContext context: Context, networkHelper: NetworkHelper): OkHttpClient { val cacheSize = (5 * 1024 * 1024).toLong() val myCache = Cache(context.cacheDir, cacheSize) return OkHttpClient.Builder() .cache(myCache) .addInterceptor { chain -> var request = chain.request() request = if (networkHelper.isNetworkConnected()) request.newBuilder().header(&quotCache-Control&quot, &quotpublic, max-age=&quot + 5).build() else request.newBuilder().header(&quotCache-Control&quot, &quotpublic, only-if-cached, max-stale=&quot + 60 * 60 * 24 * 7).build() chain.proceed(request) } .build() } @IceAndFire @Provides @Singleton fun provideIceAndFireRetrofit(client: OkHttpClient, @IceAndFire baseUrl: String): Retrofit { return Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .baseUrl(baseUrl) .client(client) .build() } @Quotes @Provides @Singleton fun provideQuotesRetrofit(client: OkHttpClient, @Quotes baseUrl: String): Retrofit { return Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .baseUrl(baseUrl) .client(client) .build() } @Provides @Singleton fun provideIceAndFireApiService(@IceAndFire retrofit: Retrofit) = retrofit.create(IceAndFireApiService::class.java) @Provides @Singleton fun provideIceAndFireApiHelper(@Quotes retrofit: Retrofit) = retrofit.create(QuotesApiService::class.java) @Provides @Singleton fun provideQuotesApiService(apiImpl: IceAndFireApiImpl): IceAndFireApiHelper = apiImpl @Provides @Singleton fun provideQuotesApiHelper(apiImpl: QuotesApiImpl): QuotesApiHelper = apiImpl }و برای تست میریم که از ویومدل داخل اکتیویتی خودمون استفاده کنیم، قبل از هر کاری انوتیشن AndroidEntryPoint رو به اکتیویتی خودمون اضافه میکنیم:@AndroidEntryPoint class MainActivity : AppCompatActivity()با اینکار به دگر اجازه میدیم که وابستگی های درخواستی رو به اکتیویتی تزریق کنه. از انوتیشن AndroidEntryPoint در موارد زیر استفاده میشه:اکتیویتیفرگمنت سرویسویوبرادکست رسیوربرای تزریق ویومدل در داخل اکتیویتی به این صورت عمل می کنیم:private val vm by viewModels<MainViewModel>()و یکی از لایودیتاها رو مشاهده می کنیم:vm.quote.observe(this, Observer { Log.e(&quotqoute&quot,it.toString()) })کار ما تمام شد و با موفقیت دگر هیلت رو پیاده سازی کردیم!سورس کد پروژه در گیتهاب موجوده و در ادامه برای استفاده از ابزارهایی نظیر MotionLayout و... از این کد استفاده می کنیم که به یک اپلیکیشن کامل تبدیل بشه!