我正在开发一个用于电子商务的 Android 应用程序,我面临着一个挑战,即在完全检索所需数据之前创建用户界面。因此,在检索过程完成之前,应用程序无法正确显示数据。
这是我目前遵循的工作流程:
用户导航到从远程服务器或数据库获取数据(例如产品详细信息、类别等)的屏幕。
布局立即膨胀,像
TextView
和RecyclerView
这样的视图显示为空或不正确,因为数据尚未准备好。
最终检索数据时(使用协程或类似的异步方法),我手动更新 UI。
这种方法会造成令人不满意的用户体验,因为在数据到达之前屏幕看起来不完整。
片段类
class HomePageFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
checkCategoryCallBack()
checkDealOfTheDayCallBack()
onClick()
}
private fun checkDealOfTheDayCallBack() {
homePageViewModel.gotDealOfTheDaySuccess.observe(viewLifecycleOwner) {
if (it == true) {
getDealOfTheDay()
} else {
homePageViewModel.getDealOfTheDay()
}
}
}
private fun checkCategoryCallBack() {
homePageViewModel.gotCategorySuccess.observe(requireActivity()) {
if (it == true) {
getCategories()
} else {
homePageViewModel.getCategories()
}
}
}
private fun getCategories() {
homePageViewModel.categoriesList.observe(requireActivity()) {
categoryAdapter = CategoryAdapter(it)
}
binding.rvCatefory.adapter = categoryAdapter
}
private fun getDealOfTheDay() {
homePageViewModel.dealOfTheDayList.observe(requireActivity()) {
productAdapter = ProductAdapter(it)
}
binding.rvDealOfTheDay.adapter = productAdapter
}
}
视图模型
class HomePageViewModel : ViewModel() {
fun getCategories() {
viewModelScope.launch(Dispatchers.IO) {
try {
_categoriesList.postValue(HomePageRepository.getCategories())
_gotCategorySuccess.postValue(true)
} catch (e: Exception) {
_gotCategorySuccess.postValue(false)
}
}
}
fun getDealOfTheDay() {
viewModelScope.launch(Dispatchers.IO) {
try {
_dealOfTheDayList.postValue(HomePageRepository.getDealOfTheDayProduct())
_gotDealOfTheDaySuccess.postValue(true)
} catch (e: Exception) {
_gotDealOfTheDaySuccess.postValue(false)
}
}
}
}
在 Android 中同步 UI 更新和异步数据检索的最佳实践是什么?具体来说,我正在寻找以下解决方案:
确保数据到达时 UI 动态更新。
改善数据检索期间的用户体验(例如占位符、加载指示器等)。
处理数据检索失败的场景(例如,没有互联网连接或 API 错误)。
我想知道可以解决这个问题的推荐方法或设计模式(例如,MVVM、StateFlow、LiveData 等)。如果有工具、库或技术可以使此过程更加顺利,请告诉我。
你的实现是不正确的,因为每次new数据到达时,它都会创建一个新的Adapter对象。因此,它不会利用View重用。您需要将新项目添加到列表中并调用NotifiDataItemChange()。但是,还有另一种方法可以使用 ListAdapter 作为 recyclerView 的适配器。当有任何变化时它会自动更新视图并且具有更好的性能
处理recyclerView页面分页,加载时有很好的UI效果,处理错误。您可以使用分页库。
您应该使用的设计模式。使用 MVVM + livedata 或 MVVM + StateFlow 。您应该只使用两者之一(而不是两者)以使维护更容易。
以下是为了满足该需求而对代码进行的编辑:
主页片段
class HomePageFragment : Fragment() {
private val categoryAdapter: CategoryAdapter by lazy {
CategoryAdapter(listOf<Any>())
}
private val productAdapter : ProductAdapter by lazy {
ProductAdapter(listOf<Any>())
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupCategoryRecyclerView()
setupDealOfTheDayRecyclerView()
getCategories()
getDealOfTheDay()
onClick()
}
private fun getCategories() {
homePageViewModel.getCategories()
}
private fun getDealOfTheDay() {
homePageViewModel.getDealOfTheDay()
}
private fun setupCategoryRecyclerView() {
binding.rvCatefory.adapter = categoryAdapter
homePageViewModel.categoriesList.observe(requireActivity()) {
categoryAdapter.submitList(it)
}
homePageViewModel.gotCategorySuccess.observe(requireActivity()) {
// control when success or error ...
}
}
private fun setupDealOfTheDayRecyclerView() {
binding.rvDealOfTheDay.adapter = productAdapter
homePageViewModel.dealOfTheDayList.observe(requireActivity()) {
productAdapter = productAdapter.submitList(it)
}
homePageViewModel.gotDealOfTheDaySuccess.observe(requireActivity()) {
//control when success or error
}
}
}
使用ListAdapter,您只需要添加项目,不需要进一步处理。当有新数据可用时,它会自动更新。
调用Api的时间根据公司的要求而定。但大多数情况下它会显示加载屏幕、占位符。
通常情况下,我会显示正在加载等待Api调用,当调用完成后我会隐藏它