این تعداد کد قبل و بعد از کامپایل میباشد. همانطور که میبینید تعداد خط کد ایجاد شده توسط dagger دو برابر بیشتر از Koin است.
مقایسه آماری در گوگل را در تصویر بالا مشاهده میکنید.
برخی توسعه دهندگان، Koin را بر Dagger2 ترجیح میدهند. آنها معتقد هستند که کار با Dagger2 دشوار میباشد اما ممکن است این مشکل، یک مسئلهی کوچک باشد. Dagger2 به دلیل کدهای زیاد تولید شده، برای توسعه دهندگان مشکل ایجاد میکند و رفع این مشکل، یک کابوس است. علاوه بر این، یادگیری Dagger2 برای تازهکارها دشوار میباشد، بنابراین اگر کسی به پروژه یا تیم شما بپیوندد باید زمان زیادی را صرف یادگیری Dagger2 کند.
kapt "com.google.dagger:dagger-compiler:$dagger_version"
kapt "com.google.dagger:dagger-android-processor:$dagger_version"
implementation "com.google.dagger:dagger:$dagger_version"
Class MyApplication : Application(), HasActivityInjector {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
override fun activityInjector() = dispatchingAndroidInjector
fun initDagger() {
DaggerAppComponent
.builder()
.application(this)
.build()
.inject(this)
}
}
به همین ترتیب، در همه اکتیویتیها یا در BaseActivity، باید HasSupportFragmentInjector را پیادهسازی کنیم و DispatchingAndroidInjector را تزریق کنیم.
برای ViewModelها، باید ViewModelFactory را در BaseFragment تزریق کنیم و همچنین Injectable را پیاده سازی کنیم.
برای هر ViewMode Fragment و Activity باید نحوهی تزریق آنها را به DI اطلاع دهیم. همانطور که مشاهده میکنید ActivityModule ،FragmentModule و ViewModelModule را داریم.
ActivityModule:
@Module
abstract class ActivityModule {
@ContributesAndroidInjector(modules = [FragmentModule::class])
abstract fun contributeMainActivity(): MainActivity
//Add your other activities here
}
برای فرگمنتها:
@Module
abstract class FragmentModule {
@ContributesAndroidInjector
abstract fun contributeLoginFragment(): LoginFragment
@ContributesAndroidInjector
abstract fun contributeRegisterFragment(): RegisterFragment
@ContributesAndroidInjector
abstract fun contributeStartPageFragment(): StartPageFragment
}
@Module
abstract class ViewModelModule {
@Binds
abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
@Binds
@IntoMap
@ViewModelKey(loginViewModel::class)
abstract fun bindLoginFragmentViewModel(loginViewModel: loginViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(StartPageViewModel::class)
abstract fun bindStartPageViewModel(startPageViewModel: StartPageViewModel): ViewModel
......
}
این خط کد را به Gradle پروژهی خود اضافه کنید.
implementation "org.koin:koin-android-viewmodel:$koin_version"
()single: یک Singleton را برای شما فراهم میکند.
package com.7learn.sevenlearn.di
import com.farshidabz.gettingstartkoin.data.remote.ImagesApi
import org.koin.dsl.module
import retrofit2.Retrofit
private val retrofit: Retrofit = createNetworkClient()
private val IMAGES_API: ImagesApi = retrofit.create(ImagesApi::class.java)
val networkModule = module {
single { IMAGES_API }
}
package com.7learn.sevenlearn.di
import com.farshidabz.gettingstartkoin.BuildConfig
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
private val sLogLevel =
if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
private const val baseUrl = "https://www.splashbase.co/api/v1/"
private fun getLogInterceptor() = HttpLoggingInterceptor().apply { level = sLogLevel }
fun createNetworkClient() =
retrofitClient(baseUrl, okHttpClient(true))
private fun okHttpClient(addAuthHeader: Boolean) = OkHttpClient.Builder()
.addInterceptor(getLogInterceptor()).apply { setTimeOutToOkHttpClient(this) }
.addInterceptor(headersInterceptor(addAuthHeader)).build()
private fun retrofitClient(baseUrl: String, httpClient: OkHttpClient): Retrofit =
Retrofit.Builder()
.baseUrl(baseUrl)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
fun headersInterceptor(addAuthHeader: Boolean) = Interceptor { chain ->
chain.proceed(
chain.request().newBuilder()
.addHeader("Content-Type", "application/json")
.also {
if (addAuthHeader) {
// it.addHeader("Authorization", wrapInBearer(UserInfoPref.bearerToken))
}
}
.build()
)
}
private fun setTimeOutToOkHttpClient(okHttpClientBuilder: OkHttpClient.Builder) =
okHttpClientBuilder.apply {
readTimeout(30L, TimeUnit.SECONDS)
connectTimeout(30L, TimeUnit.SECONDS)
writeTimeout(30L, TimeUnit.SECONDS)
}
package com.7learn.sevenlearn.di
import com.farshidabz.gettingstartkoin.data.repository.ImagesRepo
import com.farshidabz.gettingstartkoin.utils.LocationHandler
import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module
val repositoryModule = module {
single { ImagesRepo(androidContext(), imagesApi = get()) }
single { LocationHandler() }
}
package com.7learn.sevenlearn.di
import com.farshidabz.gettingstartkoin.view.main.MainActivityViewModel
import org.koin.android.viewmodel.dsl.viewModel
import org.koin.dsl.module
val viewModelModule = module {
viewModel { MainActivityViewModel(get()) }
}
private val retrofit: Retrofit = createNetworkClient()
private val generalApi: GeneralApi = retrofit.create(GeneralApi::class.java)
private val authApi: AuthApi = retrofit.create(AuthApi::class.java)
val viewModelModule = module {
viewModel { LoginFragmentViewModel(get()) }
viewModel { StartPageViewModel() }
}
کلاس viewModels را به عنوان viewModel در یک ماژول تعریف میکنیم. Koin یک ViewModel به چرخهی حیات ViewModelFactory میدهد و به اتصال آن به current component کمک میکند.
همانطور که میبینید ما یک متد ()get به سازنده LoginFragmentViewModel داریم. این تابع ساخت نمونهای از LoginFragmentViewModel را تصمیم گیری میکند. اینجا AuthRepo است.
startKoin(this, listOf(repositoryModule, networkModule, viewModelModule))
private val startPageViewModel: StartPageViewModel by viewModel()
اگر به یادگیری بیشتر در زمینهی برنامه نویسی اندروید علاقه داری، با شرکت در دوره آموزش برنامه نویسی اندروید در کمتر از یکسال به یک توسعهدهنده اندروید همه فن حریف تبدیل میشوی که آمادهی استخدام، دریافت پروژه و حتی پیادهسازی اپلیکیشن خودت هستی.