Created
November 15, 2018 03:52
-
-
Save marukami/3024dd7ae399a4a33df3041a9af84401 to your computer and use it in GitHub Desktop.
MvRx Dagger Boilerplate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package au.tilbrook.mvrx.dagger | |
import androidx.fragment.app.FragmentActivity | |
import androidx.lifecycle.ViewModel | |
import com.airbnb.mvrx.BaseMvRxViewModel | |
import com.airbnb.mvrx.MvRxState | |
import com.airbnb.mvrx.MvRxViewModelFactory | |
import javax.inject.Provider | |
interface ViewModelFactory { | |
fun create(state: MvRxState): ViewModel | |
} | |
interface HasDaggerMvRxViewModelFactory { | |
val factory: DaggerMvRxViewModelFactory | |
} | |
class DaggerMvRxViewModelFactory( | |
private val creators: MutableMap<Class<out ViewModelFactory>, Provider<ViewModelFactory>> | |
) { | |
fun <T : ViewModelFactory, R : ViewModel> create( | |
modelClass: Class<T>, | |
state: MvRxState | |
): R { | |
var creator: Provider<out ViewModelFactory>? = creators[modelClass] | |
if (creator == null) { | |
for ((key, value) in creators) { | |
if (modelClass.isAssignableFrom(key)) { | |
creator = value | |
break | |
} | |
} | |
} | |
if (creator == null) { | |
throw IllegalArgumentException("unknown model class $modelClass") | |
} | |
try { | |
@Suppress("UNCHECKED_CAST") | |
return (creator.get() as T).create(state) as R | |
} catch (e: Exception) { | |
throw RuntimeException(e) | |
} | |
} | |
} | |
inline fun <reified F : ViewModelFactory, VM : ViewModel> FragmentActivity.daggerCreate( | |
factory: Class<F>, | |
state: MvRxState | |
): VM = | |
let { it as HasDaggerMvRxViewModelFactory } | |
.factory | |
.create(modelClass = factory, state = state) | |
class HostActivity : | |
AppCompatActivity(), | |
HasDaggerMvRxViewModelFactory { | |
@Inject lateinit var mvRxViewModelFactory: DaggerMvRxViewModelFactory | |
override val factory: DaggerMvRxViewModelFactory | |
get() = mvRxViewModelFactory | |
} | |
abstract class MvRxViewModel<S : MvRxState>(initialState: S) : BaseMvRxViewModel<S>( | |
initialState = initialState, | |
debugMode = BuildConfig.DEBUG | |
) { | |
val state: S = initialState | |
} | |
class MyViewModel @AssistedInject constructor( | |
@Assisted state: MvRxState, | |
private val api: Api | |
) : MvRxViewModel<MyViewModelState>(state as MyViewModelState) { | |
@AssistedInject.Factory | |
interface Factory : ViewModelFactory { | |
override fun create(state: MvRxState): MyViewModel | |
} | |
companion object : MvRxViewModelFactory<MyViewModelState> { | |
@JvmStatic override fun create( | |
activity: FragmentActivity, | |
state: MyViewModelState | |
): BaseMvRxViewModel<MyViewModelState> = | |
activity.daggerCreate( | |
factory = MyViewModel.Factory::class.java, | |
state = state | |
) | |
} | |
} | |
@AssistedModule | |
@Module( | |
includes = [ | |
BindsViewModelFactoryModule::class, | |
AssistedInject_ViewModelFactoryModule::class | |
] | |
) | |
object ViewModelFactoryModule { | |
@JvmStatic | |
@Provides | |
fun providesDaggerMvRxViewModelFactory( | |
factories: MutableMap<Class<out ViewModelFactory>, Provider<ViewModelFactory>> | |
): DaggerMvRxViewModelFactory = | |
DaggerMvRxViewModelFactory(factories) | |
} | |
@Module | |
abstract class BindsViewModelFactoryModule { | |
@Binds | |
@IntoMap | |
@ViewModelFactoryKey(MyViewModel.Factory::class) | |
abstract fun bindsMyViewModelFactory( | |
factory: MyViewModel.Factory | |
): ViewModelFactory | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment