背景
如何处理网络请求和 UI 状态的对应关系,并没有严格的限制或者说对错之分,主要还是看是否适合自己的业务。
这里给出一种相对通用点的方案。
封装
参考 关于Kotlin中的Nothing - 掘金 (juejin.cn)
sealed class Result<out R> {
object Loading : Result<Nothing>()
class Success<out T>(val result: T) : Result<T>()
class Error(val exception: Exception) : Result<Nothing>()
}
一次性请求的界面
对于一次性请求的界面(简单理解就是没有下拉刷新),UI 状态应该为:
- 请求返回正常的列表数据
EmptyView -> Loading -> ResultList - 请求返回空列表
EmptyView -> Loading -> EmptyView - 请求发生错误
EmptyView -> Loading -> ErrorView
class MyViewModel : ViewModel() {
private val _testLiveData = MutableLiveData<Result<List<Int>>>()
val testLiveData: LiveData<Result<List<Int>>> = _testLiveData
fun getList() {
_testLiveData.value = Result.Loading
// get list from internet
try {
_testLiveData.value = API.getList()
} catch (e: java.lang.Exception) {
_testLiveData.value = Result.Error(e)
}
}
}
class MyActivity : AppCompatActivity() {
private fun showLoading() {
// loading view
}
private fun showData(data: List<Int>) {
// result list
data?.let {
}
}
private fun showError() {
// include a retry button.
}
fun test() {
val viewModel = MyViewModel()
viewModel.testLiveData.observe(this) { result ->
when (result) {
is Result.Loading -> showLoading()
is Result.Success -> showData(result.result)
is Result.Error -> showError()
}
}
}
}
可重复请求的界面
对于可重复发起请求的界面(简单理解为有下拉刷新),不同的点在于如果发生错误,应该先判断下当前界面是否为空界面,如果为空则显示 ErrorView;已经有数据显示出来的情况下就弹个 Toast 即可,这样就不会让之前的列表数据变为不可见(同时,这种情况下是不需要展示 Retry
按钮的,因为再次下拉就相当于点击重试按钮了)。
fun test() {
val viewModel = MyViewModel()
viewModel.testLiveData.observe(this) { result ->
when (result) {
is Result.Loading -> showLoading()
is Result.Success -> showData(result.result)
is Result.Error -> {
if (recyclerViewAdapter.isEmpty()) {
showError()
} else {
ToastUtils.showShort(result.exception.message)
}
}
}
}
}
网友评论