0

RecyclerView's LayoutManager class defines a function called onAdapterChanged(). If you call RecyclerView.setAdapter() when a LayoutManager is already attached, LayoutManager.onAdapterChanged() gets called as expected.

However, if you call RecyclerView.setAdapter() before you attach the LayoutManager, onAdapterChanged() doesn't fire when you do attach it, meaning there doesn't seem to be a way for a late-attached LayoutManager to get the currently-attached Adapter.

This surprised me as I thought it would call it, passing 'null' for oldAdapter, but that isn't the case.

So, barring things like explicitly passing an adapter to the LayoutManager ourselves, is there anything in the current API which would expose the current Adapter to a LayoutManager?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286
  • Can't you just pass the adapter to your Layout Manager as an argument in the constructor? – Twometer Oct 17 '17 at 21:54
  • As I said, I'm looking for something that doesn't require that. The LayoutManager can be set in a layout file so that wouldn't be applicable. I think the solution is to grab it both with the onAdapterChanged, as well as in the OnAttachedToWindow which is handed the RecyclerView (so you can just grab it there.) – Mark A. Donohoe Oct 17 '17 at 21:56
  • I love when people vote things down that are a) valid questions, and b) do so with no feedback at all. Really annoying. Definitely not a friend of S/O! – Mark A. Donohoe Oct 18 '17 at 15:35
  • 1
    That's not a problem of SO but a problem of the people. Of what use is it for someone to just click the "Vote down" button for no reason? Right, none. – Twometer Oct 18 '17 at 15:36
  • No, I meant *they* are definitely not a friend of SO because they don’t know what it’s used for... asking and answering questions, and offering suggestions on different approaches. A down-vote without at least a comment does none of the above. – Mark A. Donohoe Oct 18 '17 at 15:39

2 Answers2

2

Ok, I have a workable solution. LayoutManager defines onAttachedToWindow() which, as it's name implies, is called when the RecyclerView the LayoutManager is set on gets attached to a Window. The sole argument of that method is the RecyclerView instance being attached. Using that, you simply call getAdapter() and store away the result as needed.

To track changes after the LayoutManager has been set, you use onAdapterChanged() as mentioned in the question above.

Finally, for completeness, you can also override onDetachedFromWindow if you're interested when it's being detached, although if it is, your layout code won't fire anyway so not sure this part is necessary.

Here's the relevant bits...

private RecyclerView.Adapter adapter;

@Override public void onAttachedToWindow(RecyclerView recyclerView){

    super.onAttachedToWindow(recyclerView);

    this.adapter = recyclerView.getAdapter();
}

@Override public void onAdapterChanged(RecyclerView.Adapter oldAdapter, RecyclerView.Adapter newAdapter){

    super.onAdapterChanged(oldAdapter, newAdapter);

    this.adapter = newAdapter;
}

You can also add this, should you have a need (possibly clean-up, etc...):

@Override public void onDetachedFromWindow(RecyclerView recyclerView, Recycler recycler)
{
    super.onDetachedFromWindow(recyclerView, recycler);

    this.adapter = null;
}

That way you're always guaranteed to have the then-current (if any) adapter when you get to your layout code.

Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286
1

What you can try is as you mentioned in the comment to listen to OnAttachedToWindow and read the adapter from the RecyclerView that's passed in from there and then you can listen for adapter changes in onAdapterChanged.

But you can try to look into the source code of findViewByPosition using the Android Studio Decompiler (I can't do that because I'm on my mobile phone) and see how they did it there. The javadoc of that method says "Finds the view which represents the given adapter position" so I assume they have access to the adapter there and so you could just get the adapter the same way it's done in there.

If that is solved otherwise or the adapter can't be retrieved from there, the first approach you proposed definitely works.

Twometer
  • 1,561
  • 2
  • 16
  • 24