RecyclerView GetChildViewHolder vs FindViewHolderForLayoutPosition

Nathan Sokalski 4,111 Reputation points
2021-05-20T04:32:42.13+00:00

This is not exactly a problem, but more of a clarification of a difference. RecyclerView has GetChildViewHolder & FindViewHolderForLayoutPosition methods for finding a ViewHolder. I would have thought that the following two statements would return the same thing:

rv.FindViewHolderForLayoutPosition(index) as MyViewHolder

rv.GetChildViewHolder(rv.GetChildAt(index)) as MyViewHolder

But they don't seem to be doing that. They both use the index of the vh in the layout, correct? Is there a difference between these statements? Are there scenarios in which they would & wouldn't act the same? I am ending up in a lot of situations in which one works and the other doesn't, but I can't figure out how to determine when to use which one. Any ideas?

Developer technologies | .NET | Xamarin
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. JessieZhang-MSFT 7,716 Reputation points Microsoft External Staff
    2021-05-20T10:08:33.513+00:00

    Hello,

    Welcome to our Microsoft Q&A platform!

    From the android document RecyclerView ,we could know:

    1.findViewHolderForLayoutPosition

    @Nullable open fun findViewHolderForLayoutPosition(position: Int): RecyclerView.ViewHolder?  
    

    Return the ViewHolder for the item in the given position of the data set as of the latest layout pass.
    This method checks only the children of RecyclerView. If the item at the given position is not laid out, it will not create a new one.

    Note that when Adapter contents change, ViewHolder positions are not updated until the next layout calculation. If there are pending adapter updates, the return value of this method may not match your adapter contents. You can use #ViewHolder#getBindingAdapterPosition() to get the current adapter position of a ViewHolder. If the Adapter that is assigned to the RecyclerView is an adapter that combines other adapters (e.g. ConcatAdapter), you can use the ViewHolder#getBindingAdapter()) to find the position relative to the Adapter that bound the ViewHolder.

    When the ItemAnimator is running a change animation, there might be 2 ViewHolders with the same layout position representing the same Item. In this case, the updated ViewHolder will be returned.

    2.getChildViewHolder

    open fun getChildViewHolder(@NonNull child: View): RecyclerView.ViewHolder!  
    

    Retrieve the ViewHolder for the given child view.
    The Parameters View is the Child of this RecyclerView to query for its ViewHolder

    Note:I tested on my demo with the following code,and whether I used method getChildViewHolderor method findViewHolderForLayoutPosition, the effect is the same :

    private RecyclerView.ViewHolder nextStickHolder(RecyclerView parent, int currPos) {  
        int childCount = parent.getChildCount();  
        if (childCount == 1) {  
            return null;  
        }  
        for (int i = 1; i < childCount; i++) {  
            View child = parent.getChildAt(i);  
            int childPos = parent.getChildAdapterPosition(child);  
            Log.d("Test","childPos = " + childPos);  
            Log.d("Test","getChildViewHolder = " + parent.getChildViewHolder(child));  
            Log.d("Test","findViewHolderForLayoutPosition = " + parent.findViewHolderForLayoutPosition(childPos));  
    
            if (mProvider.isStick(childPos) && childPos > currPos) {  
                //return parent.getChildViewHolder(child);    
                return parent.findViewHolderForLayoutPosition(childPos);  
            }  
        }  
        return null;  
    }  
    

    The log is:

    2021-05-20 18:01:51.296 31227-31227/com.abc.test D/Test: childPos = 1
    2021-05-20 18:01:51.296 31227-31227/com.abc.test D/Test: getChildViewHolder = ViewHolder{b8f8646 position=1 id=-1, oldPos=-1, pLpos:-1}
    2021-05-20 18:01:51.296 31227-31227/com.abc.test D/Test: findViewHolderForLayoutPosition = ViewHolder{b8f8646 position=1 id=-1, oldPos=-1, pLpos:-1}
    2021-05-20 18:01:51.296 31227-31227/com.abc.test D/Test: childPos = 2
    2021-05-20 18:01:51.296 31227-31227/com.abc.test D/Test: getChildViewHolder = ViewHolder{a477f5d position=2 id=-1, oldPos=-1, pLpos:-1}
    2021-05-20 18:01:51.296 31227-31227/com.abc.test D/Test: findViewHolderForLayoutPosition = ViewHolder{a477f5d position=2 id=-1, oldPos=-1, pLpos:-1}
    2021-05-20 18:01:51.296 31227-31227/com.abc.test D/Test: childPos = 3
    2021-05-20 18:01:51.296 31227-31227/com.abc.test D/Test: getChildViewHolder = ViewHolder{d9f06cc position=3 id=-1, oldPos=-1, pLpos:-1}
    2021-05-20 18:01:51.297 31227-31227/com.abc.test D/Test: findViewHolderForLayoutPosition = ViewHolder{d9f06cc position=3 id=-1, oldPos=-1, pLpos:-1}
    2021-05-20 18:01:51.297 31227-31227/com.abc.test D/Test: childPos = 4
    2021-05-20 18:01:51.297 31227-31227/com.abc.test D/Test: getChildViewHolder = ViewHolder{ccc4534 position=4 id=-1, oldPos=-1, pLpos:-1}
    2021-05-20 18:01:51.297 31227-31227/com.abc.test D/Test: findViewHolderForLayoutPosition = ViewHolder{ccc4534 position=4 id=-1, oldPos=-1, pLpos:-1}
    2021-05-20 18:01:51.297 31227-31227/com.abc.test D/Test: childPos = 5
    2021-05-20 18:01:51.297 31227-31227/com.abc.test D/Test: getChildViewHolder = ViewHolder{729b007 position=5 id=-1, oldPos=-1, pLpos:-1}
    2021-05-20 18:01:51.297 31227-31227/com.abc.test D/Test: findViewHolderForLayoutPosition = ViewHolder{729b007 position=5 id=-1, oldPos=-1, pLpos:-1}

    Best Regards,

    Jessie Zhang

    ---
    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.