How to convert a List<Object> to PagedList<Object> and vice-versa?
Solution 1
I'll start with the easier part, if you want to converter a PagedList<> to a a List<> you can use the snapshot()
method, as you can seen in the docs it retuns:
Returns an immutable snapshot of the PagedList in its current state.A PagedList snapshot is simply an immutable shallow copy of the current state of the PagedList as a List.
Now as for the other way around you'll need to use PagedList.Builder and for that you'd need a DataSource to create the PagedList. So a avery basic dataSource that would manage your static list would look like this:
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
}
}
As you can see you need to override the three methods loadInitial
, loadAfter
and loadBefore
in order to tell the datasource how to load the cunks of data from the list. I've wrapped you list in a provider class just for organization purposes.
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)
}
}
To use the data source to generate the PagedList you need to build a simple configuration with PagedList.Config.Builder
:
val myConfig = PagedList.Config.Builder()
.setInitialLoadSizeHint(PAGE_SIZE)
.setPageSize(PAGE_SIZE)
.build()
And then pass that to the PagedList.Builder
with the datasource:
val pagedStrings: PagedList<String> = PagedList.Builder<Int, String>(StringDataSource(StringListProvider(originalStrings)), myConfig)
.setInitialKey(0)
.build()
Now you have a PagedList in pagedStrings
.
The same thing in 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);
}
}
Config generation
PagedList.Config myConfig = new PagedList.Config.Builder()
.setInitialLoadSizeHint(PAGE_SIZE)
.setPageSize(PAGE_SIZE)
.build();
List convertion
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();
Solution 2
I have converted a List<Object>
to PagedList<Object>
by this code in kotlin
i think this code can help you
build
config
private val config = PagedList.Config.Builder() .setEnablePlaceholders(false) .setPageSize(LIST_SIZE) .build()
2.create these classes for convert and return my 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)
}
}
Pass
val myList: List<Object>
byconfig
and getPagedList<Object>
val pagedList = PagedList.Builder(ListDataSource(myList), config) .setNotifyExecutor(UiThreadExecutor()) .setFetchExecutor(AsyncTask.THREAD_POOL_EXECUTOR) .build()
Related videos on Youtube
Santanu Sur
......... A space can make a piece of CODE look ugly. print("Enjoying Kotlin : ${KotlinVersion.CURRENT}")
Updated on August 04, 2020Comments
-
Santanu Sur almost 4 years
PagedList<Object>
is used for Android's cool paging library. To make the question as minimal as possible : If i have a list of strings likeList<String> stringList; // it consists of 200 strings
I want to convert
stringList
to typePagedList<String>
likePagedList<String> pagedStringList;
And also if i have a
PagedList<Object>
how can convert it to aList<Object>
? I went through this for referenceIf i try the other way round ....
How can I convert
List<Object>
intoDataSource.Factory<Integer, Object>
..so that indirectly i can convert it intoPagedList<>
?From
DataSource.Factory<Integer, Object>
I can convert toPagedList<>
but how can I convertlist
intoPagedList<>
?-
Levi Moreira about 6 yearsdid you manage to make this work?
-
Santanu Sur about 6 yearswill try it and let you know..i know lil kotlin though..:)
-
Levi Moreira about 6 yearsawokay :) I added the java version to be more helpful, hope it works
-
-
nAkhmedov over 5 yearsWhen you build PagedList object you need to set
setNotifyExecutor
andsetFetchExecutor
methods, otherwise crash -
levibostian about 5 yearsAs nAkhmedov mentioned, you will need to set a notify and fetch executor. Here is how to create a UI thread Executor: stackoverflow.com/a/21256419/1486374
-
Johana Lopez 1327 about 5 yearsThank you. Regarding the
setNotifyExecutor
and thesetFetchExecutor
, this page has a good implementation: [riyaz-ali.github.io/android-support-paging.html]