viewholder有一个textview和imageview
textview显示用户姓名
imageview显示用户头像
在onbindviewholder时会根据item的id向服务器请求该用户的信息
由于请求是异步的,当请求成功回调设置textview和imageview的时候列表插入新信息,就会报错
错误信息如下:
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{a2d62b7 position=2 id=-1, oldPos=1, pLpos:1 scrap [attachedScrap] tmpDetached no parent}
at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5046)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5177)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5158)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2061)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1445)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1408)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:580)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:3330)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3186)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3632)
at android.view.View.layout(View.java:15718)
at android.view.ViewGroup.layout(ViewGroup.java:5039)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15718)
at android.view.ViewGroup.layout(ViewGroup.java:5039)
at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1799)
at android.view.View.layout(View.java:15718)
at android.view.ViewGroup.layout(ViewGroup.java:5039)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1077)
at android.view.View.layout(View.java:15718)
at android.view.ViewGroup.layout(ViewGroup.java:5039)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15718)
at android.view.ViewGroup.layout(ViewGroup.java:5039)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15718)
at android.view.ViewGroup.layout(ViewGroup.java:5039)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15718)
at android.view.ViewGroup.layout(ViewGroup.java:5039)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15718)
at android.view.ViewGroup.layout(ViewGroup.java:5039)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15718)
at android.view.ViewGroup.layout(ViewGroup.java:5039)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15718)
at android.view.ViewGroup.layout(ViewGroup.java:5039)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2129)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1886)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1103)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5949)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:788)
at android.view.Choreographer.doCallbacks(Choreographer.java:601)
at android.view.Choreographer.doFrame(Choreographer.java:571)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:774)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5308)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:913)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:708)
怪我咯2017-04-18 10:33:31
오류 메시지만으로는 원인 파악이 불충분합니다.
모든 비동기 이미지 로딩 프레임워크는 다음 문제를 고려하지 않습니다.
현재 ViewHolder가 요청 전의 ViewHolder인지 여부
AdapterView와 RecyclerView는 모두 뷰 재사용 메커니즘을 가지고 있습니다. 재사용되는 뷰는 ItemViewType이 동일하므로 사용자 코드의 처리 로직도 동일해야 합니다.
비동기 이미지 로딩 프레임워크 세트를 직접 구현하는 경우 Android 공식 웹사이트 문서인 UI 스레드에서 비트맵 처리를 참조할 수 있습니다
또한 View의 태그 속성을 점유하는 것은 권장되지 않습니다. 다른 목적으로 태그를 사용해야 할 수도 있기 때문입니다.
PHP中文网2017-04-18 10:33:31
UI가 아닌 스레드에서 인터페이스를 업데이트하기 때문에 오류를 보고합니다...
비동기 로딩 시 이미지 혼동을 방지하기 위해 뷰에 태그를 추가하고, 비동기 작업이 완료된 후 태그를 기준으로 로딩 여부를 결정할 수 있습니다.
大家讲道理2017-04-18 10:33:31
이 방법은 먼저 로컬 캐시가 있는지 확인하고, 없으면 서버에서 가져와야 합니다. 획득이 완료된 후 어댑터에 해당하는 데이터를 업데이트하고 목록을 업데이트합니다.