inline fun <reified T: ViewModel> AppCompatActivity.createViewModel(crossinline factory: () -> T): T = T::class.java.let { clazz ->
ViewModelProviders.of(this, object: ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if(modelClass == clazz) {
@Suppress("UNCHECKED_CAST")
return factory() as T
}
throw IllegalArgumentException("Unexpected argument: $modelClass")
}
}).get(clazz)
}
inline fun <reified T: ViewModel> Fragment.createViewModel(crossinline factory: () -> T): T = T::class.java.let { clazz ->
ViewModelProviders.of(this, object: ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if(modelClass == clazz) {
@Suppress("UNCHECKED_CAST")
return factory() as T
}
throw IllegalArgumentException("Unexpected argument: $modelClass")
}
}).get(clazz)
}
и фрагмент:
class MyFragment : Fragment(), Injectable {
private lateinit var viewModel: MyViewModel
@Inject lateinit var appComponent: AppComponent
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = createViewModel { appComponent.myViewModel() }
viewModel.getUser().observe(this) {...}
}
...
}
Просмотреть модель:
class MyViewModel @Inject constructor(private val myRepo: MyRepository): ViewModel() {
private var instance: LiveData<MyClass>? = myRepo.getInstance()
}
Мой репозиторий:
@Singleton
class MyRepository @Inject constructor(
private val myDao: MyDao,
private val executor: Executor
) {
}
Наконец, для моих классов кинжалов у меня есть двамодули:
@Module(includes = [AndroidInjectionModule::class])
abstract class AppModule {
fun application(myApplication: MyApplication): Application = myApplication
}
@Module
abstract class DataModule {
@Provides
fun myDatabase(application: Application) =
Room.databaseBuilder(application, MyDatabase::class.java, "my-database").build()
@Provides
fun myDao(): MyDao = myDatabase.myDao()
@Provides
fun providesExecutor(): Executor =
Executors.newSingleThreadExecutor()
}
И мой AppComponent:
@Singleton
@Component(modules = [AppModule::class, DataModule::class])
interface AppComponent : AndroidInjector<MyApplication> {
@Component.Builder
abstract class Builder: AndroidInjector.Builder<MyApplication>()
fun myViewModel(): MyViewModel
}
и AppInjector:
import android.app.Activity
import android.app.Application
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentActivity
import android.support.v4.app.FragmentManager
import dagger.android.AndroidInjection
import dagger.android.support.AndroidSupportInjection
import dagger.android.support.HasSupportFragmentInjector
/**
* Helper class to automatically inject fragments if they implement [Injectable].
*/
object AppInjector {
fun init(myApp: MyApplication) {
DaggerAppComponent.builder().application(myApp)
.build().inject(myApp)
myApp
.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
handleActivity(activity)
}
override fun onActivityStarted(activity: Activity) {
}
override fun onActivityResumed(activity: Activity) {
}
override fun onActivityPaused(activity: Activity) {
}
override fun onActivityStopped(activity: Activity) {
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle?) {
}
override fun onActivityDestroyed(activity: Activity) {
}
})
}
private fun handleActivity(activity: Activity) {
if (activity is HasSupportFragmentInjector) {
AndroidInjection.inject(activity)
}
if (activity is FragmentActivity) {
activity.supportFragmentManager
.registerFragmentLifecycleCallbacks(
object : FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentCreated(
fm: FragmentManager,
f: Fragment,
savedInstanceState: Bundle?
) {
if (f is Injectable) {
AndroidSupportInjection.inject(f)
}
}
}, true
)
}
}
}
И
class MyApplication : Application(), HasActivityInjector {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
override fun onCreate() {
super.onCreate()
AppInjector.init(this)
}
override fun activityInjector() = dispatchingAndroidInjector
}