توسعه دهنده نِیتیوْ(Native) موبایل ( اندروید/آی او اس(کنارگذاشته شده)) Moeindeveloper.ir
استفاده از Dagger hilt به صورت پروژه محور (قسمت سوم)
قسمت های قبلی:
در قسمت دوم، یک ماژول تعریف کردیم که قراره داخل این قسمت، وابستگی هارو بهش اضافه کنیم.
برای شروع، بیس یو ار ال ها رو تامین می کنیم:
@Provides
@Singleton
fun provideIceAndFireBaseURL(): String = "https://www.anapioficeandfire.com/"
@Provides
@Singleton
fun provideQuotesBaseURL(): String = "https://got-quotes.herokuapp.com/"
خب الان ی مشکلی پیش میاد ? چون که از ما از دو وب سرویس متفاوت استفاده می کنیم و اینکه هر دو تامین کننده، ی نوع داده رو بازگشت میدن و باید به دگر بفمهمونیم که کجا از کدوم بیس یو ار ال استفاده کنه! اینجاست که ما از 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 = "https://www.anapioficeandfire.com/"
@Quotes
@Provides
@Singleton
fun provideQuotesBaseURL(): String = "https://got-quotes.herokuapp.com/"
برای مکانیزم کش و کلاینت کاستوم شده 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("Cache-Control", "public, max-age=" + 5).build()
else
request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 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 = "https://www.anapioficeandfire.com/"
@Quotes
@Provides
@Singleton
fun provideQuotesBaseURL(): String = "https://got-quotes.herokuapp.com/"
@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("Cache-Control", "public, max-age=" + 5).build()
else
request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 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("qoute",it.toString())
})
کار ما تمام شد و با موفقیت دگر هیلت رو پیاده سازی کردیم!
سورس کد پروژه در گیتهاب موجوده و در ادامه برای استفاده از ابزارهایی نظیر MotionLayout و... از این کد استفاده می کنیم که به یک اپلیکیشن کامل تبدیل بشه!
مطلبی دیگر از این انتشارات
تست نویسی چرا و چطور سری اول - "چرا تست بنویسیم؟"
مطلبی دیگر از این انتشارات
خداحافظ فایربیس : ردیابی کرش ها و مانیتورینگ برنامه با سرویس قدرتمند Yandex - AppMetrica
مطلبی دیگر از این انتشارات
اندروید و گردل: معرفی ساختار