如何将List<Object>转换为PagedList<Object>,反之亦然?

28

PagedList<Object>是用于Android的炫酷分页库。为了让问题尽可能简化:如果我有一个字符串列表

  List<String> stringList; // it consists of 200 strings

我想将 stringList 转换为类型 PagedList<String>,类似于

  PagedList<String> pagedStringList;

如果我有一个PagedList<Object>,如何将其转换为List<Object>? 我参考了这里的内容

如果我尝试反过来......

如何将List<Object>转换为DataSource.Factory<Integer, Object>,以便间接地将其转换为PagedList<>

DataSource.Factory<Integer, Object>我可以转换为PagedList<>,但是如何将list转换为PagedList<>


你成功让它工作了吗? - Levi Moreira
会尝试一下并让你知道,虽然我只懂得一点 Kotlin .. :) - Santanu Sur
好的,我添加了Java版本以提供更多帮助,希望它能正常工作。 - Levi Moreira
3个回答

12

首先,如果您想将PagedList<>转换为List<>,可以使用snapshot()方法,如文档中所示,它返回:

以其当前状态的不可变快照形式返回PagedList。PagedList快照只是当前PagedList状态的不可变浅拷贝,作为List。

至于反过来,您需要使用PagedList.Builder,并且需要一个DataSource来创建PagedList。因此,管理静态列表的非常基本的dataSource如下:

StringDataSource.kt

class StringDataSource(val provider: StringListProvider) : PageKeyedDataSource<Int, String>() {
    override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, String>) {
        val list = provider.getStringList(0, params.requestedLoadSize)
        callback.onResult(list, 1, 2)
    }

    override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, String>) {
        val list = provider.getStringList(params.key, params.requestedLoadSize)
        callback.onResult(list, params.key + 1)
    }

    override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, String>) {
        val list = provider.getStringList(params.key, params.requestedLoadSize)
        val nextIndex = if (params.key > 1) params.key - 1 else null
        callback.onResult(list, nextIndex)
    }

    companion object {
        const val PAGE_SIZE = 20
    }
}

正如您所看到的,您需要覆盖三个方法loadInitialloadAfterloadBefore,以告诉数据源如何从列表中加载数据块。我为了组织目的而将您的列表包装在提供程序类中。

StringListProvider.kt

class StringListProvider(val list: List<String>) {


    fun getStringList(page: Int, pageSize: Int): List<String> {

        val initialIndex = page * pageSize
        val finalIndex = initialIndex + pageSize
        //TODO manage index out of range
        return list.subList(initialIndex, finalIndex)
    }
}

使用数据源生成 PagedList,您需要使用 PagedList.Config.Builder 创建简单的配置:

    val myConfig = PagedList.Config.Builder()
            .setInitialLoadSizeHint(PAGE_SIZE)
            .setPageSize(PAGE_SIZE)
            .build()

然后将其与数据源一起传递给PagedList.Builder:

    val pagedStrings: PagedList<String> = PagedList.Builder<Int, String>(StringDataSource(StringListProvider(originalStrings)), myConfig)
            .setInitialKey(0)
            .build()

现在你有一个带有pagedStrings的PagedList。

同样的事情在Java中:

StringListProvider.java

public class StringListProvider {

    private List<String> list;

    public StringListProvider(List<String> list) {
        this.list = list;
    }

    public List<String> getStringList(int page, int pageSize) {
        int initialIndex = page * pageSize;
        int finalIndex = initialIndex + pageSize;

        //TODO manage out of range index

        return list.subList(initialIndex, finalIndex);
    }
}

StringDataSource.java

public class StringDataSource extends PageKeyedDataSource<Integer, String> {

    public static final int PAGE_SIZE = 20;
    private StringListProvider provider;

    public StringDataSource(StringListProvider provider) {
        this.provider = provider;
    }

    @Override
    public void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<Integer, String> callback) {
        List<String> result = provider.getStringList(0, params.requestedLoadSize);
        callback.onResult(result, 1, 2);
    }

    @Override
    public void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, String> callback) {
        List<String> result = provider.getStringList(params.key, params.requestedLoadSize);
        Integer nextIndex = null;

        if (params.key > 1) {
            nextIndex = params.key - 1;
        }
        callback.onResult(result, nextIndex);
    }

    @Override
    public void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, String> callback) {
        List<String> result = provider.getStringList(params.key, params.requestedLoadSize);
        callback.onResult(result, params.key + 1);
    }
}

配置生成

    PagedList.Config myConfig = new PagedList.Config.Builder()
            .setInitialLoadSizeHint(PAGE_SIZE)
            .setPageSize(PAGE_SIZE)
            .build();
列表转换
    List<String> myList = new ArrayList<>();
    StringListProvider provider = new StringListProvider(myList);
    StringDataSource dataSource = new StringDataSource(provider);
    PagedList<String> pagedStrings = new PagedList.Builder<Integer, String>(dataSource, myConfig)
            .setInitialKey(0)
            .build();

4
构建 PagedList 对象时需要设置 setNotifyExecutorsetFetchExecutor 方法,否则会崩溃。 - nAkhmedov
1
正如nAkhmedov所提到的,您需要设置一个通知和获取执行器。以下是创建UI线程Executor的方法:https://dev59.com/72Ei5IYBdhLWcg3wd8Gu#21256419 - levibostian
关于setNotifyExecutorsetFetchExecutor,这个页面有一个很好的实现:[https://riyaz-ali.github.io/android-support-paging.html]。谢谢。 - Johana Lopez 1327

3

我用Kotlin将一个List<Object>转换为PagedList<Object>,代码如下: 这段代码可以帮助你:

  1. build config

    private val config = PagedList.Config.Builder()
            .setEnablePlaceholders(false)
            .setPageSize(LIST_SIZE)
            .build()
    

2.创建这些类来转换并返回我的PagedList<Object>

     class ListDataSource<T>(private val items: List<T>) : PositionalDataSource<T>() {
            override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<T>) {
                callback.onResult(items, 0, items.size)
    }

            override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<T>) {
                val start = params.startPosition
                val end = params.startPosition + params.loadSize
                callback.onResult(items.subList(start, end))
    }
}

        // UiThreadExecutor implementation example
       class UiThreadExecutor : Executor {
            private val handler = Handler(Looper.getMainLooper())
            override fun execute(command: Runnable) {
               handler.post(command)
    }
}
  1. Pass val myList: List<Object> by config and get PagedList<Object>

    val pagedList = PagedList.Builder(ListDataSource(myList), config)
                                .setNotifyExecutor(UiThreadExecutor())
                                .setFetchExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
                                .build()
    

0

这是我解决问题的方法,希望能对你有所帮助。

val items = List<Item>.... //this can be equal to your mutable list
val config = PagedList.Config.Builder()
                        .setPageSize(items.size)
                        .setEnablePlaceholders(false)
                        .setInitialLoadSizeHint(items.size)
                        .build()

val pagedList = PagedList.Builder(ListDataSource(items),config)
                .setNotifyExecutor (UiThreadExecutor ())
                .setFetchExecutor (AsyncTask.THREAD_POOL_EXECUTOR)
                .build ()


class UiThreadExecutor: Executor {
        private val handler = Handler (Looper.getMainLooper ())
        override fun execute (command: Runnable) {
            handler.post (command)
        }
    }

class ListDataSource (private val items: List<Item>): PageKeyedDataSource<Int, Item>() {
            override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Item>) {
                callback.onResult (items, 0, items.size)
            }
    
            override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Item>) {
    
            }
    
            override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, Item>) {
    
            }
        }

其他资源:Android - 如何将列表转换为分页列表


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接