Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/211.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 使用特定于UI的数据增强PagedList且不破坏MVVM模式的最佳方法_Android_Mvvm_Android Mvvm - Fatal编程技术网

Android 使用特定于UI的数据增强PagedList且不破坏MVVM模式的最佳方法

Android 使用特定于UI的数据增强PagedList且不破坏MVVM模式的最佳方法,android,mvvm,android-mvvm,Android,Mvvm,Android Mvvm,我不熟悉MVVM模式,但我非常喜欢PagedList如何简化存储库中分页数据的处理 但现在我有以下情况: 我使用如下方法创建了存储库: fun <T> getLibraryItems(mapper: (ItemInfo) -> T): LiveData<PagedList<T>> { return dataSource .getLibraryItems() .map(mapper)

我不熟悉MVVM模式,但我非常喜欢PagedList如何简化存储库中分页数据的处理

但现在我有以下情况:

  • 我使用如下方法创建了存储库:

    fun <T> getLibraryItems(mapper: (ItemInfo) -> T): LiveData<PagedList<T>> {
            return dataSource
                .getLibraryItems()
                .map(mapper)
                .toLiveData()
    }
    
    fun getLibraryItems():LiveData

其中
ItemInfo
是特定于存储库的,不“知道”UI

  • 接下来,我想用特定于UI的数据“增强”这个数据对象(映射到另一个UI数据对象),我只能从上下文感知组件(例如,它的可绘制资源)中获得这些数据
但是我不能直接从
PagedList
映射到另一个
PagedList
,如果我需要,我需要更新数据源以接受“mapper”功能,如下所示:

fun <T> getLibraryItems(mapper: (ItemInfo) -> T): LiveData<PagedList<T>> {
        return dataSource
            .getLibraryItems()
            .map(mapper)
            .toLiveData()
}
fun-getLibraryItems(映射器:(ItemInfo)->T):LiveData{
返回数据源
.getLibraryItems()
.map(mapper)
.toLiveData()
}
通过这种方式,我可以将
ItemInfo
映射到特定于UI的类型
T
,但我不能在ViewModel中这样做,因为在ViewModel中加载可绘制资源(据我所知)是反模式的


我不明白我应该如何以及在何处称之为“映射器”,它应该是活动/片段,还是我缺少smth和过于复杂的事情。

我认为有可能按照您的建议将数据映射到ViewModel中,但不是在那里加载可绘制资源,而是只传递其标识符。然后在您的UI层(RecyclerView适配器、活动或其他)中,通过其标识符加载资源。这样,您就不必在ViewModel中处理特定于上下文的方法。另外,如果你不想处理Android资源ID(例如R.Dababy.MyOxId),你必须保留你自己的ID系统,然后将它映射到UI层内的Android资源ID,虽然我个人认为这个冗长的复杂。
编辑:在重新阅读你的问题后,我发现我的帖子没有完全回答这个问题,所以这里有更多关于架构的内容: 由于您希望将域对象映射到特定于UI的对象,因此在ViewModel中这样做不是最佳实践,也不是一种方法,这是正确的。因此,正确的方法是在显示对象之前在UI层中进行此类映射。由于您使用PagedList,我可以假设您的RecyclerView适配器扩展了PagedListAdapter。然后,您可以创建一个抽象来支持适配器内部的映射

抽象类MyPageDapter(
val数据映射器:(T)->R,
diffCallback:DiffUtil.ItemCallback
):PagedListAdapter(diffCallback){
fun getMappeItem(position:Int)=dataMapper.invoke(getItem(position))
}
类库项目适配器(
dataMapper:(LibraryItem)->UILibraryItem,
):MyPagedAdapter(数据映射器,/*在此处提供差异回调*/){
/*在此处实现onCreateViewHolder和getItemViewType*/
覆盖BindViewHolder(holder:ViewHolderType,position:Int){
val项目=GetMappeItem(位置)
//配置视图保持架以显示所选项目
}
}
//然后在片段/活动中:
val mapper:(LibraryItem)->UILibraryItem={/*使用上下文感知组件为UI*/}创建对象
recyclerView.adapter=LibraryItemAdapter(映射器)
附言:我还想强调的是,将ViewModel/Repository/其他地方的整个列表映射到另一个包含可绘制、位图或任何其他大型结构的类是一个坏主意,最终可能会导致内存中充斥着可绘制的内容,而这些内容目前可能还没有显示出来。只有当你打算使用你的抽绳时,才可以使用它们,不要将它们存储在列表中。我最初的回答和后来的编辑都会阻止你这么做

p.p.S.:不要在映射器中投入太多的工作,因为当用户快速滚动一个大列表时,它可能会大量加载UI线程。在域/存储库层执行所有业务逻辑