Android开发经验谈Android开发程序员

使用 dagger-android 注入 ViewModel

2019-10-31  本文已影响0人  追风筝的boy

获取 ViewModel实例的一般做法

class MainViewModel : ViewModel() {

    // 这里的代码,在所有的 viewModel 中都需要在写一遍,就是所谓的`Boilerplate code`
    class Factory : ViewModelProvider.Factory {
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            @Suppress("UNCHECKED_CAST")
            return MainViewModel() as T
        }
    }
}

class MainActivity : AppCompatActivity() {

    private lateinit var viewModel: MainViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel = ViewModelProviders.of(this, MainViewModel.Factory()).get(MainViewModel::class.java)
        setContentView(R.layout.activity_main)
    }
}

使用 dagger-android 来减少 boilerplate

class MainActivity : DaggerAppCompatActivity() {

    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
    private lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel = viewModelProvider(viewModelFactory)
        setContentView(R.layout.activity_main)
    }
}

inline fun <reified T: ViewModel> AppCompatActivity.viewModelProvider(provider: ViewModelProvider.Factory): T {
    return ViewModelProviders.of(this, provider).get(T::class.java)
}

class MainViewModel @Inject constructor(): ViewModel()
@Module
@Suppress("UNUSED")
abstract class ViewModelModule {

    @Binds
    internal abstract fun bindViewModelFactory(factory: AppViewModelFactory): ViewModelProvider.Factory
}

class AppViewModelFactory @Inject constructor(
    private val creators:  Map<Class<out ViewModel>,@JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        val find = creators.entries.find { modelClass.isAssignableFrom(it.key) }
        val creator = find?.value ?: throw IllegalArgumentException("unknown modelClass class $modelClass")
        return try {
            @Suppress("UNCHECKED_CAST")
            creator.get() as T
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }
}
@Module
abstract class MainActivityModule {

    @Binds
    @IntoMap
    @ViewModelKey(MainViewModel::class)
    abstract fun viewModel(viewModel: MainViewModel): ViewModel
}

如果你想在项目中集成可能需要用到的代码

@Singleton
@Component(
    modules = [
        AndroidInjectionModule::class,
        AppModule::class,
        ActivityBindingModule::class,
        ViewModelModule::class
    ]
)
interface AppComponent : AndroidInjector<MainApplication> {

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance application: MainApplication): AppComponent
    }
}

@Module
abstract class AppModule

@Module
abstract class ActivityBindingModule {

    @ActivityScope
    @ContributesAndroidInjector(modules = [MainActivityModule::class])
    internal abstract fun mainActivity(): MainActivity
}

@Module
@Suppress("UNUSED")
abstract class ViewModelModule {

    @Binds
    internal abstract fun bindViewModelFactory(factory: AppViewModelFactory): ViewModelProvider.Factory
}
inline fun <reified T: ViewModel> AppCompatActivity.viewModelProvider(provider: ViewModelProvider.Factory): T {
    return ViewModelProviders.of(this, provider).get(T::class.java)
}
@Module
abstract class NewActivityModule {

    @Binds
    @IntoMap
    @ViewModelKey(NewViewModel::class)
    abstract fun viewModel(viewModel: NewViewModel): ViewModel
}

class NewActivity() {

    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
    private lateinit var viewModel: MainViewModel
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel = viewModelProvider(viewModelFactory)
        ...
    }
}

class NewViewModel : ViewModel()

@Target(
    AnnotationTarget.FUNCTION,
    AnnotationTarget.PROPERTY_GETTER,
    AnnotationTarget.PROPERTY_SETTER
)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
上一篇下一篇

猜你喜欢

热点阅读