Dagger2下的ViewModel

Posted 不会写代码的丝丽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dagger2下的ViewModel相关的知识,希望对你有一定的参考价值。

前言

本文需要一定的储备知识,可参阅博主其他文章:
Dagger2 生成类初探
viewModel源码分析

假设我们想我们的ViewModel注入一些Dagger2所提供的依赖怎么办?直接给ViewModel构造函数注入?
如下代码

//MyViewModel.java
public class MyViewModel extends ViewModel 
    @Inject
    @Named("ActivityStr")
    String applicationMsg;

    @Inject
    public MyViewModel() 

    


//MainActivity.kt
class MainActivity : AppCompatActivity() 

    @Inject
    @Named("ActivityStr")
    lateinit var applicationMsg: String
    //直接注入
    @Inject
    lateinit var viewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) 
        androidInjection.inject(this);
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

     
    


上面的代码没有编译问题,并且viewModel也会被注入ActivityStr字符串,但是viewmodel会丢失状态!!
上面的代码在旋转屏幕时,viewmodel会被重建,因为viewmodel没有放入activity.viewModelStore.

如何将viewmoel放入activity.viewModelStore?仅能通过ViewModelProvider构造的viewmodel才会放入.

  • 如下代码:
  override fun onCreate(savedInstanceState: Bundle?) 
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        val viewModelProvider =
            ViewModelProvider(viewModelStore, ViewModelProvider.NewInstanceFactory())
		
		//用ViewModelProvider创建的viewmodel会放入viewModelStore.从而保证回收时viewmodel不会重建.
        val viewmodel = viewModelProvider.get(MyViewModel::class.java)
    

所以我们可以通过自定义一个ViewModelProvider.FactoryviewModelProvider,然后通过自定义Factory获取dagger生成的viewmodel返回即可.

//MyViewModelFactory.java
public class MyViewModelFactory implements ViewModelProvider.Factory 


    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) 
        return null;
    


问题又来了MyViewModelFactory又怎么拿到对应的dagger生成viewmodel?
在这种情况下仅能将自己也交付给dagger

@Qualifier
@Documented
@Retention(RUNTIME)
public @interface ViewModuleScope 



@Singleton
public class MyViewModelFactory implements ViewModelProvider.Factory 

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) 
        //从集合中返回一个
        return (T) viewModelsMap.get(modelClass).get();
    


    Map<Class<?>, Provider<ViewModel>> viewModelsMap;

//    /**
//     * 构造函数要求dagger2传入一个map.
//     * key为viewmodel类名
//     */
    @Inject
    public MyViewModelFactory(
            @ViewModuleScope
            Map<Class<?>, Provider<ViewModel>> viewModelsMap) 
        this.viewModelsMap = viewModelsMap;
    





问题又来了dagger怎么构造Map<Class<? extends ViewModel>, Provider<ViewModel>>集合对象?

我们只需要使用Dagger2的多重绑定即可


@Module
public abstract class ViewModules 
    @Binds
    abstract ViewModelProvider.Factory bindViewModelFactory(MyViewModelFactory factory);

    @Binds
    @IntoMap
    @ViewModuleScope
    @ClassKey(MyViewModel.class)
    abstract ViewModel provideViewModel(MyViewModel myViewModel);

    @Binds
    @IntoMap
    @ViewModuleScope
    @ClassKey(MyViewModel2.class)
    abstract ViewModel provideViewModel2(MyViewModel2 myViewModel);



实际使用


class MainActivity : AppCompatActivity() 

  
    @Inject
    lateinit var factory: ViewModelProvider.Factory

    override fun onCreate(savedInstanceState: Bundle?) 
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val viewModelProvider = ViewModelProvider(this, factory)
        val myViewModel = viewModelProvider[MyViewModel::class.java]
        Log.e("MainActivity","viewModel $myViewModel.hashCode()")
    


输出:

 E/MainActivity: viewModel 197683938
-----------------旋转屏幕----------
 E/MainActivity: viewModel 197683938

另外关于网上流传的自定义MapKey,和上面原理一样就不在过多说明.不过需要注意添加下面的依赖

 compileOnly "com.google.auto.value:auto-value-annotations:1.8.1"
 kapt "com.google.auto.value:auto-value:1.8.1"

以上是关于Dagger2下的ViewModel的主要内容,如果未能解决你的问题,请参考以下文章

Dagger2:如果没有 @Provides-annotated 方法,就无法提供 ViewModel

如何在 ViewModel 中访问 SharedPreferences?

Dagger MVVM - ViewModel注入为null

Kotlin dagger 2 Android ViewModel 注入错误

Dagger2图文完全教程

Android二手交易平台,dagger2+mvp+Bmob后台云搭建