Skip to content

Instantly share code, notes, and snippets.

@twogood
Created January 25, 2019 22:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save twogood/d3aeae04905ced9c0dce691a60cba7ce to your computer and use it in GitHub Desktop.
Save twogood/d3aeae04905ced9c0dce691a60cba7ce to your computer and use it in GitHub Desktop.
Android Jetpack ViewModel, Dagger 2, Kotlin coroutines
package example
import android.arch.lifecycle.ViewModel
import android.arch.lifecycle.ViewModelProvider
import dagger.Binds
import dagger.MapKey
import dagger.Module
import javax.inject.Inject
import javax.inject.Provider
import kotlin.reflect.KClass
@Suppress("UNCHECKED_CAST")
class DaggerViewModelFactory @Inject constructor(private val viewModelsMap: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>) :
ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
val creator = viewModelsMap[modelClass] ?: viewModelsMap.asIterable().firstOrNull {
modelClass.isAssignableFrom(it.key)
}?.value ?: throw IllegalArgumentException("unknown model class $modelClass")
return try {
creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
@Module
abstract class ViewModelFactoryModule {
@Binds
abstract fun bindViewModelFactory(viewModelFactory: DaggerViewModelFactory): ViewModelProvider.Factory
}
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
package example
import android.arch.lifecycle.ViewModel
import android.arch.lifecycle.ViewModelProvider
import android.arch.lifecycle.ViewModelProviders
import javax.inject.Inject
abstract class FragmentWithViewModels : ScopedFragment() {
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
}
inline fun <reified T : ViewModel> FragmentWithViewModels.getViewModel(): T {
return ViewModelProviders.of(this, viewModelFactory).get(T::class.java)
}
package example
import android.os.Bundle
import android.support.v4.app.Fragment
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlin.coroutines.CoroutineContext
abstract class ScopedFragment : Fragment(), CoroutineScope {
protected lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
job = Job()
}
override fun onDestroy() {
super.onDestroy()
job.cancel()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment