分页体系结构组件的初始占位符

时间:2018-09-11 12:19:58

标签: android android-recyclerview android-architecture-components

我在项目中使用Paging Architecture Components从网络中加载列表(尚未使用数据库)。我的DataSourcePositionalDataSource的子类,而我的PagedList.Config看起来像这样:

PagedList.Config config = new PagedList.Config.Builder()
        .setPageSize(10)
        .setInitialLoadSizeHint(20)
        .setPrefetchDistance(20)
        .setEnablePlaceholders(true)
        .build();

启用了占位符,并且我在PagedListAdapter子类中处理了空的ViewHolders,以不同方式显示占位符项。当在列表末尾加载其他项目时,占位符可以很好地工作,但是我还想在加载前几项(之前之前)显示占位符项目(如常规加载指示器)。

是否可以使用分页库来执行此操作?我试图用1而不是0的位置来呼叫LoadInitialCallback.onResult(),但这只会在第一个实际项目之前创建一个占位符项目,而该占位符项目永远不会消失。

2 个答案:

答案 0 :(得分:2)

我知道这个问题还很老,但是我回答了,因为这是我结束对这个问题进行搜索的地方。在v3中,您可以将LoadStateAdapter添加到“页眉”和“页脚”中,以进行“预加载”和“附加”加载状态。初始加载将是刷新状态,该状态似乎不包括在内,但是我们可以简单地复制功能并将其扩展为包括刷新:

我只是用LoadStateHeaderAndFooter复制并添加了可用于刷新的第三个适配器

private fun PagingAdapter.withLoadStateAll(
        header: LoadStateAdapter<*>,
        footer: LoadStateAdapter<*>,
        refresh: LoadStateAdapter<*>
    ): ConcatAdapter {
        addLoadStateListener { loadStates ->
            header.loadState = loadStates.prepend
            footer.loadState = loadStates.append
            refresh.loadState = loadStates.refresh
        }
        return ConcatAdapter(refresh,header, this, footer)
    }

然后,您只需按照文档将其注册到Recycler,它就会在初始加载时显示。

recycler.adapter = adapter.withLoadStateAll(LoadAdapter(),LoadAdapter(),LoadAdapter())

如果您需要在初始加载期间显示多个项目,只需复制LoadStateAdapter并将项目数从1更改为n:

class InitialLoadAdapter(private val num : Int) : RecyclerView.Adapter<LoadViewHolder>() {

    var loadState: LoadState = LoadState.NotLoading(endOfPaginationReached = false)
        set(loadState) {
            if (field != loadState) {
                val oldItem = displayLoadStateAsItem(field)
                val newItem = displayLoadStateAsItem(loadState)

                if (oldItem && !newItem) {
                    notifyItemRangeRemoved(0,num)
                } else if (newItem && !oldItem) {
                    notifyItemRangeInserted(0,num)
                } else if (oldItem && newItem) {
                    notifyItemRangeChanged(0,num)
                }
                field = loadState
            }
        }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LoadViewHolder {
        return LoadViewHolder(parent)
    }
    override fun onBindViewHolder(holder: LoadViewHolder, position: Int) {}

    override fun getItemViewType(position: Int): Int = getStateViewType(loadState)

    override fun getItemCount(): Int = if (displayLoadStateAsItem(loadState)) num else 0

    private fun getStateViewType(loadState: LoadState): Int = 0

    private fun displayLoadStateAsItem(loadState: LoadState): Boolean {
        return loadState is LoadState.Loading || loadState is LoadState.Error
    }
}

答案 1 :(得分:0)

有一种方法可以让您传递数据集大小,我认为这正是您所缺少的。

public abstract static class LoadInitialCallback<Key, Value> {
        /**
         * Called to pass initial load state from a DataSource.
         * <p>
         * Call this method from your DataSource's {@code loadInitial} function to return data,
         * and inform how many placeholders should be shown before and after. If counting is cheap
         * to compute (for example, if a network load returns the information regardless), it's
         * recommended to pass data back through this method.
         * <p>
         * It is always valid to pass a different amount of data than what is requested. Pass an
         * empty list if there is no more data to load.
         *
         * @param data List of items loaded from the DataSource. If this is empty, the DataSource
         *             is treated as empty, and no further loads will occur.
         * @param position Position of the item at the front of the list. If there are {@code N}
         *                 items before the items in data that can be loaded from this DataSource,
         *                 pass {@code N}.
         * @param totalCount Total number of items that may be returned from this DataSource.
         *                   Includes the number in the initial {@code data} parameter
         *                   as well as any items that can be loaded in front or behind of
         *                   {@code data}.
         */
        public abstract void onResult(@NonNull List<Value> data, int position, int totalCount,
                @Nullable Key previousPageKey, @Nullable Key nextPageKey);

我尝试过,但是我都看不到预览。

检查http://youtube.com/watch?v=BE5bsyGGLf4

希望这会有所帮助