Android中使用ViewModel+Volley获取数据时如何在加载完成前显示等待提示
数据未加载完成前显示加载提示的实现方案
核心思路
通过在ViewModel内部维护加载状态LiveData,配合Volley自带的请求回调更新状态,Fragment监听状态动态切换加载提示和下拉列表的显示即可,全程不需要用到已废弃的AsyncTask。Volley本身的请求回调已经运行在主线程,无需额外做线程切换处理。
具体实现步骤
1. ViewModel新增加载状态定义与监听入口
首先定义加载状态,新增对应的LiveData,并在原有Volley请求逻辑中插入状态更新逻辑:
// 加载状态密封类,可定义在ViewModel内部或单独文件 sealed class DataLoadState { object Loading : DataLoadState() object Success : DataLoadState() data class Error(val errorMsg: String) : DataLoadState() } class MyViewModel : ViewModel() { // 原有存储下拉列表数据的LiveData val spinnerData = MutableLiveData<List<YourDataClass>>() // 新增加载状态LiveData val loadState = MutableLiveData<DataLoadState>() // 原有Volley拉取数据的方法,补充状态更新逻辑 fun fetchDataFromServer(context: Context) { // 请求开始前更新为加载中状态 loadState.postValue(DataLoadState.Loading) // 原有Volley请求逻辑 val dataRequest = JsonArrayRequest( Request.Method.GET, YOUR_API_INTERFACE, null, { response -> // 解析接口返回数据,更新列表数据 val dataList = parseResponseToYourData(response) spinnerData.postValue(dataList) // 请求成功更新状态 loadState.postValue(DataLoadState.Success) }, { error -> // 请求失败更新状态 loadState.postValue(DataLoadState.Error(error.message?:"数据请求失败")) } ) // 原有将请求加入Volley队列的逻辑 VolleyQueue.getInstance(context).addToRequestQueue(dataRequest) } }
如果使用Java开发,将密封类替换为静态常量定义加载状态(如public static final int LOADING = 0;),状态LiveData使用MutableLiveData<Integer>即可,逻辑完全一致。
2. 调整Fragment布局
在原有布局中加入加载提示控件(如ProgressBar),和下拉列表放在同一个父布局下即可,初始状态可默认隐藏。
3. Fragment监听加载状态,动态切换UI
在Fragment的onViewCreated中监听ViewModel的加载状态LiveData,根据状态切换UI展示:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 获取和MainActivity共享的ViewModel实例 val mainViewModel = ViewModelProvider(requireActivity())[MyViewModel::class.java] // 监听加载状态 mainViewModel.loadState.observe(viewLifecycleOwner) { state -> when(state) { is DataLoadState.Loading -> { // 显示加载提示,隐藏下拉列表 loadingProgressBar.visibility = View.VISIBLE dataSpinner.visibility = View.GONE } is DataLoadState.Success -> { // 隐藏加载提示,显示下拉列表并更新数据 loadingProgressBar.visibility = View.GONE dataSpinner.visibility = View.VISIBLE mainViewModel.spinnerData.value?.let { // 给下拉列表设置适配器更新数据 spinnerAdapter.updateData(it) } } is DataLoadState.Error -> { // 隐藏加载提示,展示错误信息 loadingProgressBar.visibility = View.GONE Toast.makeText(requireContext(), state.errorMsg, Toast.LENGTH_SHORT).show() } } } // 页面进入时触发数据拉取,或在数据库更新完成后触发此方法即可 mainViewModel.fetchDataFromServer(requireContext()) }
注意事项
- LiveData绑定了Fragment的生命周期,不会出现Fragment销毁后收到请求回调导致的崩溃问题
- 数据库更新操作完成后仅需要调用一次
fetchDataFromServer方法触发刷新即可,不需要手动处理请求和UI的时序问题
内容的提问来源于stack exchange,提问作者man_idk
相关产品推荐
相关产品推荐

