RecyclerView.ViewHolder-getLayoutPosition 대 ​​getAdapterPosition


87

새로운 지원 라이브러리 버전 (22.x) 이후 getPosition()의 방법 RecyclerView.ViewHolder클래스는 주제에 언급 된 방법 대신에 사용되지 않습니다. 나는 문서를 읽는 것과 실제로 차이를 얻지 못합니다. 누군가 평신도 용어의 차이점을 설명 할 수 있습니까?

다음 사용 사례가 있습니다. 어댑터에 List를 지정하고 각 목록 항목에 대한 추가 정보를 연결할 수 있기를 원합니다. 나는 포지션-엑스트라 매핑을 가지고 있으며, 보유자들이 그들의 포지션에 대한 엑스트라를 가져 와서 작업을 할 수 있도록 매핑이 가능합니다. 홀더에서 어떤 방법을 사용해야합니까?

인덱스 0과 1의 목록 항목이 위치가 바뀔 때 홀더 위치는 어떻게됩니까? 메소드는 무엇을 반환합니까?

답변:


114

문서가 충분하지 않아 죄송합니다.

어댑터 내용이 변경되면 (그리고 호출 할 때 notify***()) RecyclerView는 새 레이아웃을 요청합니다. 그 순간부터 레이아웃 시스템이 새 레이아웃 (<16ms)을 계산하기로 결정할 때까지 레이아웃이 아직 어댑터 변경 사항을 반영하지 않았기 때문에 레이아웃 위치와 어댑터 위치가 일치하지 않을 수 있습니다.

사용 사례에서 데이터는 어댑터 콘텐츠와 관련이 있으므로 (데이터가 어댑터 변경과 동시에 변경된다고 가정합니다) adapterPosition.

그러나 호출하는 경우 notifyDataSetChanged()모든 것을 무효화하므로 RecyclerView는 다음 레이아웃이 계산 될 때까지 ViewHolder의 어댑터 위치를 알지 못합니다. 이 경우 ( ) getAdapterPosition()를 반환 합니다.RecyclerView#NO_POSITION-1

당신이 호출 한 경우하지만 말을 할 수 notifyItemInserted(0), getAdapterPosition()위치에 이전에 있던 ViewHolder의이 0반환 시작됩니다 1즉시. 따라서 세분화 된 알림 이벤트를 전달하는 한 항상 양호한 상태에 있습니다 (새 레이아웃이 아직 계산되지 않은 경우에도 어댑터 위치를 알고 있음).

또 다른 예로, 사용자 클릭에 대해 무언가를하고있는 경우를 getAdapterPosition()반환 NO_POSITION하면 사용자가 무엇을 클릭했는지 모르기 때문에 해당 클릭을 무시하는 것이 가장 좋습니다 (예 : 항목 조회를위한 안정적인 ID와 같은 다른 메커니즘이없는 경우).

레이아웃 위치가 좋을 때 편집

당신이 사용하는 말을하자 LinearLayoutManager및 현재 클릭 한 항목 위의 ViewHolder에 액세스하려면. 이 경우 레이아웃 위치를 사용하여 위의 항목을 가져와야합니다.

mRecyclerView.findViewHolderForLayoutPosition(myViewHolder.getLayoutPosition() - 1)

레이아웃 위치는 사용자가 현재 화면에서보고있는 것과 일치하기 때문에 사용해야합니다.


1
나는 약간 놀았고 getAdapterPosition () 메서드가 항상 나에게 -1을 반환한다는 것이 밝혀졌습니다. 나는 그것을 디버깅했고 그 이유는 메서드의 코드 (final ViewParent parent = itemView.getParent (); if (! (parent instanceof RecyclerView)) {return -1;} 항상 if 블록, 즉 리사이클 러 뷰에 들어갑니다. 내 셀 뷰의 부모가 아닙니다. 어떻게 할 수 있습니까? 홀더를 만드는 코드는 다음과 같습니다. return MyViewHolder (LayoutInflater.from (viewGroup.getContext ()). inflate (R.layout.test_list_item, viewGroup, false)); (다른 의견에 계속됩니다.)
wujek

코드를 변경하여 inflate (R.layout.test_list_item, viewGroup, true); ( '루트에 연결'의 경우 참), Android는 다음을 던집니다. java.lang.IllegalStateException : 지정된 하위에 이미 상위가 있습니다. 먼저 자식의 부모에서 removeView ()를 호출해야합니다. 그렇다면 리사이클 러 뷰에 올바르게 연결된 뷰가있는 뷰 홀더를 만드는 올바른 방법은 무엇입니까? 이상하게도 부모가 null이기 때문에 getAdapterPosition ()이 -1을 반환하더라도 다른 모든 것은 잘 작동합니다.
wujek

1
레이아웃 인플레이터의 부울 매개 변수는 "addToParent"입니다. 추가하는 것은 LayoutManager의 책임이므로 false 여야합니다. 이미 위치를 전달받은 onBind에서 getAdapterPosition을 호출하고 있다고 생각합니다. 기술적으로 뷰 홀더는 onBind가 반환 된 후 해당 위치를 나타냅니다. Btw, 우리는 getAdapter 위치가 분리되어 있어도 유효한 위치 (가능한 경우)를 반환하도록 업데이트했으며 곧 출시 될 예정입니다.
yigit

당신이 맞아요, 저는 onBind에서 getAdapterPosition을 호출하고 있습니다. 대신이 경우 어떻게해야하나요? 일부 견해의 상태에 영향을 미치는 정보를 얻을 수있는 위치가 필요합니다. 이 경우 getLayoutPosition을 호출해도 괜찮습니까?
wujek

5
onBind 메소드에 전달되는 위치 매개 변수를 사용해야합니다.
yigit

2


차이 (들)을 주장하기 위해 getAdapterPosition(), getLayoutPosition()및도 position; 다음과 같은 경우를 알 수 있습니다.

1. 메소드의 position인수 onBindViewHolder():

를 사용하여 position뷰에 데이터를 바인딩 할 수 있으며 position인수 를 사용 하여이를 수행 하는 것은 괜찮지 만 position인수를 사용 하여 사용자 클릭을 처리 하는 것은 좋지 않으며 사용하는 경우 "다음으로 처리하지 말 것"이라는 경고가 표시 position됩니다. 고정하고 holder.getAdapterPosition()대신 사용 ".

2. getAdapterPosition():

이 메서드는 항상 업데이트 된 어댑터의 holder. 항목을 클릭 할 때마다 어댑터에 position. 그래서 당신은 어댑터의 논리 측면 에서이 항목의 최신 위치를 얻을 수 있습니다.

3. getLayoutPosition():

때때로,을 찾을 필요 position예를 들어, 업데이트 된 레이아웃 (사용자가 지금 보는 것을 마지막으로 통과 레이아웃)의 측면에서 : 사용자가 3 분의 1을 요청하는 경우 position그가 볼 수 있고 사용 swipe/ dismiss항목이나 애니메이션을 적용 또는 항목에 대한 장식은 getLayoutPosition()대신 사용 하는 것이 더 낫습니다 getAdapterPosition(). 왜냐하면 가장 최근에 전달 된 레이아웃과 관련하여 항목의 위치를 ​​항상 다루고 있기 때문입니다.


이에 대한 자세한 내용은 여기를 참조 하십시오 . . .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.