版权声明:本文为博主原创文章,转载请说明出处。 https://blog.csdn.net/qq_30889373/article/details/81806129
介绍
只是个人学习笔记,有不对的地方欢迎留言
先了解一些基础知识
@Binds
声明 Person 提供 是由 Student构建
public class Person {
@Inject Person(){}
}
// 学生
public class Student extends Person {
@Inject Student(){}
}
@Module
public abstract class MainModule {
@Binds
public abstract Person bindMainTarger(Student student);
}
@IntoSet @IntoMap @IntoXXXX
这边文章写的很详细,我就不再重写了
https://blog.csdn.net/io_field/article/details/71170727
先介绍一下 非dagger2 时 MVVM如何设计
databinding的使用 如果有不了解的 推荐下面视频
Android Data Binding实战-入门篇
https://www.imooc.com/learn/719
Android Data Binding实战-高级篇
https://www.imooc.com/learn/720
我们简单来说一下
override fun onCreate(savedInstanceState: Bundle?) {
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this,R.layout.activity_main)
binding.vm = ViewModelProviders.of(this, viewModelFactory).get(MainViewModel::class.java)
binding.vm.start()
}
但是大多数情景下,我们都是自定义ViewModelProvider.Factory,然后在create时
进行 构建不同参数的 ViewModel
自定义Factory
public class ViewModelFactory extends ViewModelProvider.NewInstanceFactory {
private ViewModelFactory(Application application, TasksRepository repository) {
mApplication = application;
mTasksRepository = repository;
}
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
if (modelClass.isAssignableFrom(MainViewModel.class)) {
//noinspection unchecked
return (T) new MainViewModel(mApplication, mTasksRepository);
}
throw new IllegalArgumentException("Unknown ViewModel class: " + modelClass.getName());
}
}
上方已明确说了一些构建繁琐的问题,下面也就引入 dagger2 你将看到为什么这么多人喜欢 dagger2 的原因
dagger2 实战MVVM
参考谷歌:
https://github.com/googlesamples
ViewModel相关
// dagger2 自定义key
@MustBeDocumented
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
ViewModelFactory
class ViewModelFactory @Inject constructor(
private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>)
: ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
var creator: Provider<ViewModel>? = 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 {
return creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
ViewModel
class WelcomeViewModel @Inject constructor(application: Application) : AndroidViewModel(application) {
// 自行定义功能
fun start(){
// ...
}
}
scope声明
@Scope
@Retention(RUNTIME)
annotation class ActivityScope
@Scope
@Retention(RetentionPolicy.RUNTIME)
annotation class FragmentScope
module
全局
@Module
internal object AppModule {
@Singleton
@Provides
@JvmStatic
fun getHttpService(): IOfficialApi {
# 这里是我自定义的库,你们改为 正常 retrofit构建即可
return RetrofitClient.Builder(
IOfficialApi::class.java,
true,
IConstantPool.sCommonUrl,
headers = { HashMap() }
).create()
}
}
对应 activity
@Module
internal abstract class WelcomeViewModelModule
@Binds
@IntoMap
@ViewModelKey(WelcomeViewModel::class)
abstract fun bindMainViewModel(viewModel: WelcomeViewModel): ViewModel
}
AllActivitiesModule
@Module
internal abstract class AllActivitiesModule {
@Binds
abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
@ActivityScope
@ContributesAndroidInjector(modules = [WelcomeViewModelModule::class])
abstract fun contributeWelcomeActivitytInjector(): WelcomeActivity
}
这里单独说一下
ContributesAndroidInjector,其实是精简了以下代码
我们查看编译出来的 kapt 文件
public abstract class AllActivitiesModule_ContributeWelcomeActivitytInjector {
private AllActivitiesModule_ContributeWelcomeActivitytInjector() {}
@Binds
@IntoMap
@ActivityKey(WelcomeActivity.class)
abstract AndroidInjector.Factory<? extends Activity> bindAndroidInjectorFactory(
WelcomeActivitySubcomponent.Builder builder);
@Subcomponent(modules = WelcomeViewModelModule.class)
@ActivityScope
public interface WelcomeActivitySubcomponent extends AndroidInjector<WelcomeActivity> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<WelcomeActivity> {}
}
}
component
@Singleton
@Component(
modules = [
AndroidInjectionModule::class,
AndroidSupportInjectionModule::class,
// 全局提供的module
AppModule::class,
// 每个activity 对应的设计
AllActivitiesModule::class
]
)
interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
fun inject(app: App)
}
使用
请先build 上方代码
App
public class App extends Application implements HasActivityInjector {
@Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
@Override
public void onCreate() {
super.onCreate();
DaggerAppComponent.builder()
.application(this)
.build()
.inject(this);
// ARouter
ARouter.init(this);
}
@Override
public AndroidInjector<Activity> activityInjector() {
return dispatchingAndroidInjector;
}
}
BaseActivity
abstract class BaseActivity<in T : ViewDataBinding, vm : ViewModel>(
// 自定义布局
private val layoutResID: Int)
:AppCompatActivity(){
// mvvm
private lateinit var binding: T
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
override fun onCreate(savedInstanceState: Bundle?) {
// 注入
AndroidInjection.inject(this)
// create
super.onCreate(savedInstanceState)
// 初始化 Binding
binding = DataBindingUtil.setContentView(this, layoutResID)
// 绑定
val vm = ViewModelProviders.of(this, viewModelFactory).get(getViewModelClass())
// DataBinding
init(binding, vm)
}
/** MVVM */
abstract fun getViewModelClass(): Class<vm>
abstract fun init(binding: T, vm: vm)
}
WelcomeActivity
class WelcomeActivity : BaseActivity<ActivityWelcomeBinding,WelcomeViewModel>(
R.layout.activity_welcome
) {
override fun getViewModelClass() = WelcomeViewModel::class.java
override fun init(binding: ActivityWelcomeBinding, vm: WelcomeViewModel) {
binding.viewModel = vm
vm.start()
}
}
是不是发现 dagger2 非常好用,一句话 舒服~~