Android Jetpack MVVM封装及使用
MVVM架构图封装使用效果图demo参考
MVVM架构图
这张图清晰地展示了MVVM的三个模块:Activity / Fragment为View层,ViewModel + LiveData为ViewModel层,Repository(管理本地和远端数据)为Model层。
封装
理清了MVVM的层次,接下来尝试对其进行简单的封装。
1.BaseRepository
提取了生成Service类的方法apiService供子类使用。 提取了请求接口方法request,出现异常情况则throw,让ViewModel层处理。
abstract class BaseRepository {
protected fun
return ApiClient.createService(tClass)
}
@Throws(Exception::class)
protected suspend fun
val baseData = block()
if (baseData.errorCode == 0) {
if (baseData.data == null) {
throw Exception("baseData.data is null!")
}
return baseData.data
} else {
throw ApiException(baseData.errorCode, baseData.errorMsg)
}
}
}
2.BaseViewModel
提取了launch方法,可以一次调用多个接口;处理Model层抛出的异常。
abstract class BaseViewModel : ViewModel() {
private val _dataLoading = MutableLiveData
val dataLoading: LiveData
protected fun launch(
block: suspend () -> Unit,
error: suspend (Int) -> Unit = {
}
) {
viewModelScope.launch {
_dataLoading.value = true
try {
block.invoke()
} catch (e: Exception) {
when (e) {
is ApiException -> {
// TODO: use Toast to show errorMsg
error(e.code)
}
is ConnectException, is UnknownHostException, is SocketTimeoutException -> {
// TODO: use Toast to show exception message
Log.e("Exception", e.localizedMessage)
}
}
} finally {
_dataLoading.value = false
}
}
}
}
3.BaseVmActivity
提取viewModel字段及创建方法;添加viewModel的dataLoading字段的监听,实现统一的Loading管理。
abstract class BaseVmActivity
protected val viewModel by lazy { ViewModelProvider(this).get(getVmClass()) }
private val loadingDialog by lazy { ContentLoadingDialog(this) }
abstract fun getVmClass(): Class
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
addObserver()
}
open fun addObserver() {
viewModel.dataLoading.observe(this) {
if (it) {
loadingDialog.showDialog()
} else {
loadingDialog.hideDialog()
}
}
}
}
使用
1.HomeRepository
添加hotkeys和banners方法,请求 玩Android 开放API 的搜索热词及首页banner接口。
class HomeRepository : BaseRepository() {
suspend fun hotkeys(): List
return request {
apiService(HomeService::class.java).hotkeys()
}
}
suspend fun banners(): List
return request {
apiService(HomeService::class.java).banners()
}
}
}
2.HomeViewModel
调用HomeRepository的hotkeys和banners方法(未处理banners接口返回数据,这里只做多个接口调用的演示),返回搜索热词列表,通过DataBinding自动将处理后的hotkeyText显示到TextView上。
class HomeViewModel : BaseViewModel() {
private val repository by lazy { HomeRepository() }
private val hotkeyList = MutableLiveData>()
private var _hotkeyText: LiveData
val hotkeyText: LiveData
fun hotkeys() {
launch({
hotkeyList.value = repository.hotkeys()
repository.banners()
})
}
private fun createHotkeyText(list: List
val text = StringBuilder()
for (key in list) {
text.append("${key.name}\n")
}
return text.toString()
}
}
3.MvvmActivity
利用DataBinding将viewModel赋值给viewmodel,实现数据绑定。
class MvvmActivity : BaseVmActivity
override fun getBinding(): ActivityMvvmBinding {
return ActivityMvvmBinding.inflate(layoutInflater).apply {
viewmodel = viewModel
lifecycleOwner = this@MvvmActivity
}
}
override fun getVmClass(): Class
return HomeViewModel::class.java
}
}
效果图
接口请求太快了,loading都没有来得及显示。。。
demo
上面只展示了MVVM在Activity中的使用,demo里也有在Fragment中使用的代码。如需参考完整代码,请移步Github仓库:MVVM Demo
参考
【1】Android Jetpack系列之MVVM使用及封装
推荐链接
发表评论