Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jetpack Paging 3 support #88

Open
krossovochkin opened this issue Jun 13, 2020 · 5 comments
Open

Jetpack Paging 3 support #88

krossovochkin opened this issue Jun 13, 2020 · 5 comments

Comments

@krossovochkin
Copy link

Hi,

Paging 3 is a complete rework of previous paging solution by Google.
Adapter delegates have support for version 2.

Would be good to have support for version 3 as well.
Though version 3 is just announced and is currently in alpha, still would be good to have some initial support.

https://developer.android.com/topic/libraries/architecture/paging/v3-overview

Thank you

@krossovochkin
Copy link
Author

I've tried to make an adapter, similar to what there is for v2 paging. But faced an issue that I couldn't find a way to extract "currentList" data from the PagingDataAdapter (or it's differ).
Seems like paging lib goes directly into "1 view type" per whole adapter (with separate implementation for header and footer) and doesn't expose list directly.

So, workarounded that in the following way:

class PagingDataDelegationAdapter<T : Any>(
    diffCallback: DiffUtil.ItemCallback<T>,
    vararg delegates: AdapterDelegate<List<T>>
) : PagingDataAdapter<T, RecyclerView.ViewHolder>(diffCallback) {

    private val delegatesManager: AdapterDelegatesManager<List<T>> = AdapterDelegatesManager()

    init {
        delegates.forEach { delegatesManager.addDelegate(it) }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return delegatesManager.onCreateViewHolder(parent, viewType)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
//// here directly taking item and passing it to onBindViewHolder (wrapping into list to conform the adapterdelegates API)
        val item =
            getItem(position) // Internally triggers loading items around items around the given position
        val delegate = delegatesManager.getDelegateForViewType(holder.itemViewType)
            ?: throw NullPointerException(
                "No delegate found for item at position = "
                        + position
                        + " for viewType = "
                        + holder.itemViewType
            )

        delegate.onBindViewHolder(listOf(item as T), 0, holder, emptyList())
    }

    override fun getItemViewType(position: Int): Int {
///// here just return whatever as multiple view types are not supported
        return 0
    }

    override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
        delegatesManager.onViewRecycled(holder)
    }

    override fun onFailedToRecycleView(holder: RecyclerView.ViewHolder): Boolean {
        return delegatesManager.onFailedToRecycleView(holder)
    }

    override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
        delegatesManager.onViewAttachedToWindow(holder)
    }

    override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
        delegatesManager.onViewDetachedFromWindow(holder)
    }
}

Could be good if someone also took a look at that. Maybe there is something that needs to be updated in the API of adapterdelegates, or maybe something can be incorporated as a feedback to Jetpack team (so they might expose "currentList" or something similar in the public api)

Thank you

@sockeqwe
Copy link
Owner

Do you want to send me a PR for this?

@krossovochkin
Copy link
Author

Hi @sockeqwe

I'd be happy to help with that, but I have a feeling that it would be not that easy.
What I've posted above is definitely a hack and I don't think it should be added like this into lib.

Main issue I see is in AdapterDelegate interface. It is low-level interface in the whole lib, and it defines everything in terms of adapter's underlying list and position.

public abstract class AdapterDelegate<T> {

    protected abstract boolean isForViewType(@NonNull T items, int position);

    protected abstract void onBindViewHolder(@NonNull T items, int position,
                                             @NonNull RecyclerView.ViewHolder holder, @NonNull List<Object> payloads);

Here items are meant as "datasource". Though all of the implementations in library seem to rely on List to be a datasource.

In Paging 3 lists are not exposed and not used inside. There are NullPaddedLists, but it is separate interface which doesn't relate to general List interface.

Instead there are methods to get itemCount and item by position.
It is technically possible to create some Provider interface and base solution on AdapterDelegate<Provider>.
But this would require to create whole new branch of the classes (including bindings etc)

Another workaround would be to make method "getCurrentList" as in Paging2 adapter based on getItem(position) and getItemCount. But that would have bad performance I guess.

So, I'd be happy to help, but atm I'm a bit stuck on what is the right direction.

krossovochkin added a commit to krossovochkin/AdapterDelegates that referenced this issue Jul 1, 2020
@PavelSidyakin
Copy link

Hello!
@sockeqwe Do you have plans to support the paging 3 officially in the nearest future?

@suhocki
Copy link

suhocki commented Nov 27, 2020

Hello,
@sockeqwe I would be very happy if Paging 3 support becomes available in the near future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants