web-dev-qa-db-ja.com

Android Paging ComponentのPagedListAdapterからアイテムを削除する方法

REST APIから通知データのリストをロードするために、レトロフィット付きのページングを使用しました。

通知項目の削除ボタンを押すと、削除APIを呼び出して削除します。削除API応答の成功後にPagedListAdapterからそれを削除する適切な方法は何ですか? PagedListまたはPagedListAdapterは、インデックスまたはオブジェクトによるアイテムの削除をサポートしていません。

DataSource.validate()を呼び出そうとしましたが、現在のページからではなく、最初からリロードします。

13
phamxuanlu

公式ドキュメント によると:

ネットワークAPIがリスト内の単一のアイテムへの更新を通知するなど、より詳細な更新信号がある場合は、ネットワークからメモリにデータをロードすることをお勧めします。次に、メモリ内のスナップショットをラップするDataSourceを介して、そのデータをPagedListに提示します。インメモリコピーが変更されるたびに、以前のDataSourceを無効にし、スナップショットの新しい状態をラップする新しいデータソースを作成できます。

PagedListは不変であるため、変更することはできません。あなたがする必要があるのは:

  1. 可変リストLを維持し、サーバー応答をカスタムDataSourceに保存します。
  2. それをLoadInitialCallback.onResult()に渡します(PagedListLによってサポートされています)。
  3. Lに好きなことをしてください。
  4. DataSource.invalidate()を呼び出して新しいデータソースとペアリングするため、DataSource.loadInitial()が呼び出され、手順3の変更が反映されます。
5
jaychang0917

最もエレガントなソリューションではありませんが、機能しています。たとえば、リスト全体を再フェッチするのではなく、アイテムを削除するときに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)
            }
        }
    }
}

0
Antonis Radz