Android Dagger (四) MVVM模式的实践 Kotlin

版权声明:本文为博主原创文章,转载请说明出处。 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 的原因

扫描二维码关注公众号,回复: 3725007 查看本文章

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 非常好用,一句话 舒服~~

猜你喜欢

转载自blog.csdn.net/qq_30889373/article/details/81806129