github大哥的
https://github.com/emedinaa/kotlin-mvvm
View
页面需要的变量
```kotlin
private val viewModel by viewModels<MuseumViewModel> {
Injection.provideViewModelFactory()
}
//这个viewmodel说委托给viewModels类做的
private lateinit var adapter: MuseumAdapter
private lateinit var recyclerView: RecyclerView
private lateinit var layoutError: View
private lateinit var textViewError: TextView
private lateinit var layoutEmpty: View
private lateinit var progressBar: View
将viewModel的创建和UI的创建独立一个函数出来
```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_museum)
setupViewModel()
setupUI()
}
UI部分
private fun setupUI() {
recyclerView = findViewById(R.id.recyclerView)
layoutError = findViewById(R.id.layoutError)
layoutEmpty = findViewById(R.id.layoutEmpty)
progressBar = findViewById(R.id.progressBar)
textViewError = findViewById(R.id.textViewError)
adapter = MuseumAdapter(viewModel.museums.value ?: emptyList())
//传入一个list类型的对象初始化,该list对象存在viewModel中
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = adapter
}
view model部分
设置观察者,因为MVVM是双向绑定的,数据出现改变的时候会通知
private fun setupViewModel() {
viewModel.museums.observe(this, renderMuseums)
//传入的是一个Observer<T>类型的函数方法
viewModel.isViewLoading.observe(this, isViewLoadingObserver)
viewModel.onMessageError.observe(this, onMessageErrorObserver)
viewModel.isEmptyList.observe(this, emptyListObserver)
}
observers观察者部分
有变化就改变view层,并且通知适配器更新
private val renderMuseums = Observer<List<Museum>> {
Log.v(TAG, "data updated $it")
layoutError.visibility = View.GONE
layoutEmpty.visibility = View.GONE
adapter.update(it)
}
private val isViewLoadingObserver = Observer<Boolean> {
Log.v(TAG, "isViewLoading $it")
val visibility = if (it) View.VISIBLE else View.GONE
progressBar.visibility = visibility
}
private val onMessageErrorObserver = Observer<Any> {
Log.v(TAG, "onMessageError $it")
layoutError.visibility = View.VISIBLE
layoutEmpty.visibility = View.GONE
textViewError.text = "Error $it"
}
private val emptyListObserver = Observer<Boolean> {
Log.v(TAG, "emptyListObserver $it")
layoutEmpty.visibility = View.VISIBLE
layoutError.visibility = View.GONE
}
如果你需要更新数据,你可以调用viewmodel中的loadMuseums方法
override fun onResume() {
super.onResume()
viewModel.loadMuseums()
}
override fun onDestroy() {
super.onDestroy()
Injection.destroy()
}
ViewModel
继承自viewModel
livedata不可修改,mutableLiveData可修改,把可修改的暴露给Activity
private val _museums = MutableLiveData<List<Museum>>().apply { value = emptyList() }
val museums: LiveData<List<Museum>> = _museums
private val _isViewLoading = MutableLiveData<Boolean>()
val isViewLoading: LiveData<Boolean> = _isViewLoading
private val _onMessageError = MutableLiveData<Any>()
val onMessageError: LiveData<Any> = _onMessageError
private val _isEmptyList = MutableLiveData<Boolean>()
val isEmptyList: LiveData<Boolean> = _isEmptyList
/*
如果你需要这些数据只被加载一次,可以考虑init中调用loadMuseums()。这个时候,如果你旋转屏幕,这个方法不会被调用
init {
//loadMuseums()
}
*/
fun loadMuseums() {
_isViewLoading.value = true
//repository是由构造函数传入的,fetchMuseum是其下的一个方法
/*
fun fetchMuseums(callback: OperationCallback<Museum>) {
museumDataSource.retrieveMuseums(callback)
}
museumDataSoruce是一个接口,内部有fetchMuseums方法,传入一个callback
*/
repository.fetchMuseums(object : OperationCallback<Museum> {
override fun onError(error: String?) {
_isViewLoading.value = false
_onMessageError.value = error
}
override fun onSuccess(data: List<Museum>?) {
_isViewLoading.value = false
if (data.isNullOrEmpty()) {
_isEmptyList.value = true
} else {
_museums.value = data
}
}
})
}