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
涉及類:
- InjectorUtils: 單例模式完成給Activity/Fragment提供註冊ViewModel 的方法,實例化請求數據的類,將數據類和ViewModel 進行綁定
- PictureRepository ,圖片請求類,完成數據請求或數據庫查詢,其實就是提供獲取數據的
- 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 {
})
}
}
是不是方便很多,
代碼