简体   繁体   中英

Android Paging 3 library, grouping items

We are developing a chat application. If messages contain images, and they come one after another, we in adapter group these images in one message.

Question 1

In the database, and in the rest of API we have these messages separately, but in the adapter, we group them to display to the user as one big message with small icons of images inside.

We want to implement a paging library to have the possibility to scroll to any message in history. Currently, we are using a RemoteMediator<Int, Message> , which makes requests to our server, and gets messages. To store these messages we are using Room , which returns PagingSource<Int, Message> . To display messages we are using PagingDataAdapter

Everything works well, the question is how we can implement this grouping images logic in Paging 3? On what steps and when we can make this change and group message in one?

Example :

Message1_Text1 - Message2_Image1 - Message3_Image2 - Message4_Text2

After grouping, we should receive

Message1_Text1 - Message2_(Image1_Image2) - Message3_Text2

Question 2

Depending on what messages are before and after we display messages differently, for example, we display profile icon only on the first message, all other messages from the same user displayed without a profile icon.

We can change our data in PagingData.map{} but we don't have any information about before and after items. How can be this achieved?

I am using paging with Jetpack Compose, I got a way to access the before and after item, making it possible to finish some grouping work. This might be a dumb way, but it works:

Create a function like:

fun <T : Any> LazyListScope.itemsBeforeAndAfter(
    items: LazyPagingItems<T>,
    key: ((item: T) -> Any)? = null,
    itemContent: @Composable LazyItemScope.(value: T?, beforeValue: T?, AfterValue: T?) -> Unit
) {
    items(
        count = items.itemCount,
        key = if (key == null) null else { index ->
            val item = items.peek(index)
            if (item == null) {
                index
            } else {
                key(item)
            }
        }
    ) { index ->
        val beforeValue = if (index - 1 < 0) null else items.peek(index - 1)
        val afterValue = if (index + 1 >= items.itemCount) null else items.peek(index + 1)
        itemContent(items[index], beforeValue, afterValue)
    }
}

Now we can access the values we need:

val lazyPagingItems = pagingDataFlow.collectAsLazyPagingItems()
            LazyColumn() {
                itemsBeforeAndAfter(
                    items = lazyPagingItems,
                    key = { // your own key logic }) { value, beforeValue, AfterValue ->
                    // Do whatever you want here
                }
            }

In this way I broke the PagingPlaceholderKey , so don't forget to disable it:

Pager(
    PagingConfig(
        pageSize = 20,
        enablePlaceholders = false
    )
) { // pagingSource }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM