【知識整理】RecyclerView内部Bug???焦らないでゆっくり解決しよう
12716 ワード
一、前に書く
これも久しぶりに一ヶ月Blogを書いていないので、最近妹紙に仕事を探して、いろいろなことを誘拐して、しかし卵がありません.ええ、多くの友达、成都はソフトウェアテスト、オンライン運営、製品アシスタントのパートナーが必要で、急いで私の話をしました.この妹紙、学習能力はとても良くて、資質も悪くなくて、専門の成績は全体的に学年の第2位で、大学院生を推薦して(最近すでに放棄することを決定しました)、心が動くより行動して、遅くなったらチャンスがなくて、急いで私を信じましょう.
この記事は、次のように同期して公開されます.
簡単な本:http://www.jianshu.com/p/d520e6559433
CSDN:http://blog.csdn.net/nanchen_lsl/article/details/72829093
二、RecyclerViewの内部バグに驚いた?
いい加減にして、とっくにツッコミを書かれている可能性のあるRecyclerViewのバグについて話しましょう.
あなたたちが出会ったかどうか分からないが、RecyclerViewが押されたとき、あなたはそれが好きで、あなたは黙ってそれを使って、甚だしきに至ってはその丈夫さ(艹、このようにしても性、愛)に手を放さない.あなたは、これがこんなに長い間出てきたので、きっと大丈夫だと思います.ええ、大丈夫です.しかし、ある高速スライドの中で、Boomは、崩壊しました!一瞬にして顔を殴る.
ログを見て次のものを手に入れます.
雑一は配列の境界を越えているように見えますか?NO NO NO、このログは私たちのコードとは関係ないように見えますね.何度もGoogleが発見したが、これはGoogleプログラマーの鍋のようだ.内部バグ?このTM公式の問題は、あなたと何の関係がありますか?RecyclerViewは使わないでしょう?
あなたは優秀なプログラム猿で、いつも問題を避けるのではなく、どのように解決するかを考えるべきです.しかし、これは一つの問題を説明しています.人が聖賢でなければ、誰が過ちを犯すことができないのか、Googleプログラマーのような牛の存在さえ問題になります.私たちは......へへへ.
このクラッシュの原因は,バインドされた集合リストのデータとRecycerViewのデータが一致しない場合,更新メソッドを呼び出すと再現されることが明らかである.
三、どうやって解決しますか.
クラッシュの原因はclear後、すばやくスライドする可能性が高いと言われていますが、新しいデータが来ていないため、RecyclerViewが次のItemを更新してロードする必要がある場合、データソースが見つからずクラッシュが発生します.
だから、そうである以上、クリアしたときに、RecyclerViewのスライドを禁止することで解決できるに違いない.コードは次のとおりです.
四、他の人の意見
人、考え、いつも奇妙だ.
クラッシュの原因は明らかですが、集合リストを更新した後、RVadapterのnotifyXXXXメソッドを呼び出すと、adapterの更新予想インタフェースと実際の集合更新結果が異なると、この異常が発生します.信じないで勝手にこの状況の発生をシミュレートすることができます.
このような結論を得た人もいます
1、RVadapterのnotifyDataSetChangedメソッドが実行された後、一定時間以内にあなたのセットを更新した場合(メインスレッドでセットを更新するかどうかにかかわらず)、この更新はリアルタイムでコントロールに反応し、つまりあなたのコントロール表示も更新されます.
2、notifyItemRangeInsertedのような方法を呼び出す前に、あなたの集合がどのように更新されたのかをよく考えてください.結論1を参考にして、結論1はあなたの判断に影響します.
五、この問題を解決する正しい姿勢?
明らかに、上の方法はあまり使いにくいので、研究を続けてみると、直接下の方法を採用すればよく解決できることが分かった.
多くの研究を経て、以下のように、私たちの問題を完璧に解決できることが分かった.
1、LinearLayoutManagerを複写する
2、はい、そうです.LayoutManaerを直接交換すればOKです
六、最後に書く
どうしてこれで解決できるのか聞かないでください.私は大声であなたに教えて、私も知りません!
どうすればいいのか、私も仕方がない.
これも久しぶりに一ヶ月Blogを書いていないので、最近妹紙に仕事を探して、いろいろなことを誘拐して、しかし卵がありません.ええ、多くの友达、成都はソフトウェアテスト、オンライン運営、製品アシスタントのパートナーが必要で、急いで私の話をしました.この妹紙、学習能力はとても良くて、資質も悪くなくて、専門の成績は全体的に学年の第2位で、大学院生を推薦して(最近すでに放棄することを決定しました)、心が動くより行動して、遅くなったらチャンスがなくて、急いで私を信じましょう.
この記事は、次のように同期して公開されます.
簡単な本:http://www.jianshu.com/p/d520e6559433
CSDN:http://blog.csdn.net/nanchen_lsl/article/details/72829093
二、RecyclerViewの内部バグに驚いた?
いい加減にして、とっくにツッコミを書かれている可能性のあるRecyclerViewのバグについて話しましょう.
あなたたちが出会ったかどうか分からないが、RecyclerViewが押されたとき、あなたはそれが好きで、あなたは黙ってそれを使って、甚だしきに至ってはその丈夫さ(艹、このようにしても性、愛)に手を放さない.あなたは、これがこんなに長い間出てきたので、きっと大丈夫だと思います.ええ、大丈夫です.しかし、ある高速スライドの中で、Boomは、崩壊しました!一瞬にして顔を殴る.
ログを見て次のものを手に入れます.
1 java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 157(offset:157).state:588
2 at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3300)
3 at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3258)
4 at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1803)
5 at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1302)
6 at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1265)
7 at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1093)
8 at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:956)
9 at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:2715)
10 at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
11 at android.view.Choreographer.doCallbacks(Choreographer.java:555)
12 at android.view.Choreographer.doFrame(Choreographer.java:524)
13 at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
14 at android.os.Handler.handleCallback(Handler.java:615)
15 at android.os.Handler.dispatchMessage(Handler.java:92)
16 at android.os.Looper.loop(Looper.java:137)
17 at android.app.ActivityThread.main(ActivityThread.java:4921)
18 at java.lang.reflect.Method.invokeNative(Native Method)
19 at java.lang.reflect.Method.invoke(Method.java:511)
20 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
21 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
22 at dalvik.system.NativeStart.main(Native Method)
雑一は配列の境界を越えているように見えますか?NO NO NO、このログは私たちのコードとは関係ないように見えますね.何度もGoogleが発見したが、これはGoogleプログラマーの鍋のようだ.内部バグ?このTM公式の問題は、あなたと何の関係がありますか?RecyclerViewは使わないでしょう?
あなたは優秀なプログラム猿で、いつも問題を避けるのではなく、どのように解決するかを考えるべきです.しかし、これは一つの問題を説明しています.人が聖賢でなければ、誰が過ちを犯すことができないのか、Googleプログラマーのような牛の存在さえ問題になります.私たちは......へへへ.
このクラッシュの原因は,バインドされた集合リストのデータとRecycerViewのデータが一致しない場合,更新メソッドを呼び出すと再現されることが明らかである.
三、どうやって解決しますか.
クラッシュの原因はclear後、すばやくスライドする可能性が高いと言われていますが、新しいデータが来ていないため、RecyclerViewが次のItemを更新してロードする必要がある場合、データソースが見つからずクラッシュが発生します.
だから、そうである以上、クリアしたときに、RecyclerViewのスライドを禁止することで解決できるに違いない.コードは次のとおりです.
1 private boolean mIsRefreshing=false;
2 mRecyclerView.setOnTouchListener(
3 new View.OnTouchListener() {
4 @Override
5 public boolean onTouch(View v, MotionEvent event) {
6 if (mIsRefreshing) {
7 return true;
8 } else {
9 return false;
10 }
11 }
12 }
13 );
14 //
15 //mIsRefreshing=true;
16 // false
17 //mIsRefreshing=false;
四、他の人の意見
人、考え、いつも奇妙だ.
クラッシュの原因は明らかですが、集合リストを更新した後、RVadapterのnotifyXXXXメソッドを呼び出すと、adapterの更新予想インタフェースと実際の集合更新結果が異なると、この異常が発生します.信じないで勝手にこの状況の発生をシミュレートすることができます.
このような結論を得た人もいます
1、RVadapterのnotifyDataSetChangedメソッドが実行された後、一定時間以内にあなたのセットを更新した場合(メインスレッドでセットを更新するかどうかにかかわらず)、この更新はリアルタイムでコントロールに反応し、つまりあなたのコントロール表示も更新されます.
2、notifyItemRangeInsertedのような方法を呼び出す前に、あなたの集合がどのように更新されたのかをよく考えてください.結論1を参考にして、結論1はあなたの判断に影響します.
五、この問題を解決する正しい姿勢?
明らかに、上の方法はあまり使いにくいので、研究を続けてみると、直接下の方法を採用すればよく解決できることが分かった.
多くの研究を経て、以下のように、私たちの問題を完璧に解決できることが分かった.
1、LinearLayoutManagerを複写する
1 package com.zxedu.ischool.common;
2
3 import android.content.Context;
4 import android.support.v7.widget.LinearLayoutManager;
5 import android.support.v7.widget.RecyclerView;
6 import android.util.AttributeSet;
7
8 /**
9 * Author: nanchen
10 * Email: [email protected]
11 * Date: 2017-05-19 15:56
12 */
13
14 public class WrapContentLinearLayoutManager extends LinearLayoutManager {
15 public WrapContentLinearLayoutManager(Context context) {
16 super(context);
17 }
18
19 public WrapContentLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
20 super(context, orientation, reverseLayout);
21 }
22
23 public WrapContentLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
24 super(context, attrs, defStyleAttr, defStyleRes);
25 }
26
27 @Override
28 public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
29 try {
30 super.onLayoutChildren(recycler, state);
31 } catch (IndexOutOfBoundsException e) {
32 e.printStackTrace();
33 }
34 }
35 }
2、はい、そうです.LayoutManaerを直接交換すればOKです
1 // mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
2 // RecyclerView holder Bug
3 mRecyclerView.setLayoutManager(new WrapContentLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
六、最後に書く
どうしてこれで解決できるのか聞かないでください.私は大声であなたに教えて、私も知りません!
どうすればいいのか、私も仕方がない.