在项目中优雅的使用ViewModel

ViewModel 是jetpack(Google 提供的应用开发框架)中的解耦数据和UI,可感知生命周期的方式存储数据,可以随着Activity的生命周期进行数据的控制,解决了以前Activity的切换横竖屏重新加载数据等问题,但是ViewModel 最主要的不是保存短在的数据在其属性中,而是通过它进行数据与UI的无感知更新,

一、ViewModel 的生命周期

ViewModel 存在的时间范围是获取ViewModel 时传递给ViewModelProvider的Lifecycle,而后ViewModel一直会留存在内存中,直到存在时间范围的Lifecycle永久消失,
在这里插入图片描述

上图对应了到Activity发生屏幕旋转而结束生命周期的过程中所处的各种状态,

二、ViewModel使用

class PictureViewModel : ViewModel(){
    val pictureView: MutableLiveData<List<String>> = MutableLiveData()
}
class PictureFragment : Fragment() {
// 1. 申明ViewModel
    private lateinit var viewModel: PictureViewModel
  
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_picture, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 2. 初始化
        viewModel = ViewModelProviders.of(this).get(PictureViewModel::class.java)
        // 3.使用
        viewModel.pictureView.observe(viewLifecycleOwner, Observer { 
            
        })
    }
}

使用其实分上述三步:

  • 声明对象的类继承ViewModel
  • 在对应的类中初始化
  • 使用

这个是基本是官方提供的使用方式。但是我们需要给我们的ViewModel 传递一个参数,我们怎么做?

三、在app中统一管理我们的ViewModel

其实上面那个问题官方提供了ViewModelProvider.Factory来解决,我今天就是要通过ViewModelProvider.Factory来集中式的使用ViewModel

涉及类:

  1. InjectorUtils: 单例模式完成给Activity/Fragment提供注册ViewModel 的方法,实例化请求数据的类,将数据类和ViewModel 进行绑定
  2. PictureRepository ,图片请求类,完成数据请求或数据库查询,其实就是提供获取数据的
  3. PictureViewModelFactory 继承ViewModelProvider.Factory :实例化ViewModel

已经描述的很清楚了,看一下具体实现

根据依赖关系,可以倒先写PictureRepository,在写ViewModel,接着PictureViewModelFactory,哈哈无所谓啊

// 数据来源
class PictureRepository private constructor(private val context: Context) {


    fun getData() :MutableLiveData<List<String>>{
        // 返回珍视数据
        return MutableLiveData()
    }

    companion object {
        @Volatile
        private var instance: PictureRepository? = null
        fun getInstance(context: Context) = instance ?: synchronized(this) {
            instance ?: PictureRepository(context).also { instance = it }
        }
    }
}
// ViewModewl 传入PictureRepository,调用获取数据方法
class PictureViewModel internal constructor(repository: PictureRepository) : ViewModel(){
    val pictureView: MutableLiveData<List<String>> = repository.getData()

}
@Suppress("UNCHECKED_CAST")
class PictureViewModelFactory(private val repository: PictureRepository): ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
    // 传入PictureRepository
        return PictureViewModel(repository) as T
    }
}
object InjectorUtils {
//提供给Activity/Fragment
    fun providerPictureViewModelFactory(context: Fragment) :PictureViewModelFactory {
        return PictureViewModelFactory(getPictureRepository(context.requireContext()))
    }

    private fun getPictureRepository(context: Context): PictureRepository {
        return PictureRepository.getInstance(context.applicationContext)
    }
}

在Fragment中使用:

class PictureFragment : Fragment() {
    //    private lateinit var viewModel: PictureViewModel
    // 使用
    private val viewModel: PictureViewModel by viewModels {
        InjectorUtils.providerPictureViewModelFactory(this)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_picture, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
//        viewModel = ViewModelProviders.of(this).get(PictureViewModel::class.java)
        viewModel.pictureView.observe(viewLifecycleOwner, Observer {

        })
    }
}

是不是方便很多,
代码

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章