【问题标题】:How to remove an item from PagedListAdapter in Android Paging Component如何从 Android 分页组件中的 PagedListAdapter 中删除项目
【发布时间】:2018-08-16 10:42:24
【问题描述】:

我使用 Paging with Retrofit 从 REST API 加载通知数据列表。

当我按下通知项的删除按钮时,我会调用删除 API 将其删除。删除 API 响应成功后,将其从 PagedListAdapter 中删除的正确方法是什么? PagedListPagedListAdapter 不支持按索引或对象删除项目。

我尝试调用DataSource.validate(),但它从开始重新加载,而不是从当前页面。

【问题讨论】:

  • 您是使用网络+数据库还是只使用网络?
  • 我只使用网络。
  • 好吧,输入显示您所做工作的最小代码,以便更容易知道从哪里开始提供帮助
  • 把你到目前为止所做的事情。用最少的代码解释你的问题
  • 嘿@phamxuanlu 你找到解决办法了吗?我的 pagedListAdapter 面临同样的问题..?

标签: android android-architecture-components android-paging


【解决方案1】:

根据official doc

如果您有更精细的更新信号,例如网络 API 发出更新列表中单个项目的信号,建议将数据从网络加载到内存中。然后通过包装内存快照的 DataSource 将该数据呈现给 PagedList。每次内存中的副本更改时,都会使之前的 DataSource 失效,并且可以创建一个包装快照新状态的新数据源。

PagedList 是不可变的,因此您无法对其进行任何修改。你需要做的是:

  1. 维护一个可变列表L,将您的服务器响应存储在您的自定义DataSource中。
  2. 将其传递给LoadInitialCallback.onResult()PagedList 现在由L 支持)。
  3. 随心所欲L
  4. 调用DataSource.invalidate() 与新数据源配对,因此调用DataSource.loadInitial() 以反映步骤3 中的更改。

【讨论】:

  • 这确实有效,但它确实在invalidate()之后重新加载了所有recyclerview
  • 请您提供更多示例说明。
  • 这不是一个好主意。让它显示几页后,从列表中删除一些项目,然后调用 DataSource.invalidate。您将看到 recyclerview 显示第一页并从旧的原始位置滚动到头部位置,这是您不想要的。跨度>
  • 我认为这个想法是将远程数据作为数据源加载到列表中。您使数据源无效,这会导致从缓存列表中创建新的数据源。问题是您将两个副本缓存到内存中。此外,当来自远程的数据很大时,您将无法加载所有数据。 @孙航
【解决方案2】:

不是最优雅的解决方案,但它正在工作。例如,在删除项目而不是重新获取整个列表时使用 Firestore 分页时使用这种方法要好得多....

也可以优化,因为这只是一个草稿。主要思想是使用带有空白视图的虚拟 ViewHolder。

class PostAdapter(
    options: FirestorePagingOptions<Post>,
    private val feedViewModel: FeedViewModel
) : FirestorePagingAdapter<Post, RecyclerView.ViewHolder>(options) {

    companion object {
        private const val DELETED_VIEW_TYPE = 1
        private const val NORMAL_VIEW_TYPE = 2
    }

    private val deletedItems = arrayListOf<String>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val inflater = parent.getLayoutInflater()
        return when (viewType) {
            NORMAL_VIEW_TYPE -> {
                PostViewHolder(ItemPostBinding.inflate(inflater, parent, false))
            }
            else -> BindingViewHolder<ItemDeletedPostBinding>(
                ItemDeletedPostBinding.inflate(inflater, parent, false)
            )
        }

    }

    override fun getItemViewType(position: Int): Int {
        val item = getItem(position)?.toObject(Post::class.java)
        if (deletedItems.firstOrNull { it == item?.postId }.isNotNull()) {
            return DELETED_VIEW_TYPE
        } else {
            return NORMAL_VIEW_TYPE
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, model: Post) {
        if (holder is PostViewHolder) {
            holder.bind(model, feedViewModel)
        }
    }

    fun deleteItem(post: Post) {
        val postId = post.postId

        if (postId != null) {
            val element = currentList?.find { it.toObject(Post::class.java)?.postId == postId }
            val index = currentList?.indexOf(element)

            index?.let {
                deletedItems.add(postId)
                notifyItemChanged(it)
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-19
    • 2018-03-19
    • 1970-01-01
    • 2018-08-02
    • 2016-09-07
    • 1970-01-01
    相关资源
    最近更新 更多