我是MVVM模式的新手,但我真的很喜欢PagedList如何简化存储库中分页数据的使用。
但是现在我有以下情况:
fun getLibraryItems(): LiveData<PagedList<ItemInfo>>
其中
ItemInfo
是存储库特定的,并且不“了解” UI。但是,如果需要的话,我无法直接从
PagedList<X>
映射到另一个PagedList<Y>
-我需要更新数据源以接受“映射器”功能,如下所示:fun <T> getLibraryItems(mapper: (ItemInfo) -> T): LiveData<PagedList<T>> {
return dataSource
.getLibraryItems()
.map(mapper)
.toLiveData()
}
这样,我可以将ItemInfo
映射到特定于UI的UI类型T
,但是我无法在ViewModel中做到这一点,因为(据我所知)在ViewModel中加载Drawable资源是反模式。我不知道如何以及在何处将其称为“映射器”,应该是“ Activity ”/“片段”,还是我错过了smth和过于复杂的事物。
最佳答案
我认为有可能按照您的建议在ViewModel内映射数据,但与其在此处加载Drawable资源,不如仅传递其标识符。然后在您的UI层(RecyclerView Adapter,Activity或其他)中,通过其标识符加载资源。这样,您就不必在ViewModel中处理特定于上下文的方法。另外,如果您不想处理android资源ID(例如R.drawable.my_image),则必须保留自己的ID系统,然后将其映射到UI层内的android资源ID,尽管我个人认为这是多余的并发症。
编辑:重新阅读您的问题后,我发现我的帖子没有完全回答它,所以这里有更多关于体系结构的内容:
由于您要将域对象映射到特定于UI的对象,因此在ViewModel中这样做不是最佳实践,而不是clean architecture方式,这是正确的。因此正确的方法是在显示对象之前在UI层中进行此类映射。由于您使用PagedList,因此我可以假设您的RecyclerView适配器扩展了PagedListAdapter。然后,您可以创建抽象以支持适配器内部的映射。
abstract class MyPagedAdapter<T, R, VH: RecyclerView.ViewHolder>(
val dataMapper: (T)->R,
diffCallback: DiffUtil.ItemCallback<T>
): PagedListAdapter<T, VH>(diffCallback) {
fun getMappedItem(position: Int) = dataMapper.invoke(getItem(position))
}
class LibraryItemAdapter(
dataMapper: (LibraryItem)->UILibraryItem,
): MyPagedAdapter<LibraryItem, UILibraryItem, ViewHolderType>(dataMapper, /* provide diff callback here */) {
/* implement onCreateViewHolder and getItemViewType here */
override fun onBindViewHolder(holder: ViewHolderType, position: Int) {
val item = getMappedItem(position)
// configure view holder to display selected item
}
}
// Then inside your fragment/activity:
val mapper: (LibraryItem) -> UILibraryItem = { /* use your context-aware components to create an object for UI */ }
recyclerView.adapter = LibraryItemAdapter(mapper)
PS:我还想强调一点,将您的ViewModel/Repository/elsewhere中的整个列表映射到另一个包含Drawable,Bitmap或任何其他大型结构的类是一个坏主意,您最终可能会用Drawables淹没内存现在甚至不会显示。仅在要使用可绘制对象且不将其存储在列表中时才获取它们。我最初的答案和后来的修改都使您无法这样做P.P.S .:不要在您的映射器中进行过多的工作,因为当用户快速滚动大列表时,它可能会大量加载UI线程。在域/存储库层中执行所有业务逻辑。
关于android - 用特定于UI的数据增强PagedList且不破坏MVVM模式的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65740094/