2015年08月16日
RelativeLayoutのディテールにLisvViewを指定して、layout_heightにwrap_contentを指定した場合、getViewが指定したListの明細数より多く呼ばれる。
これは嵌りました。
最初は実害がないと思ったので放置していた事もあったのですが、レスポンスが悪いので改善しようとしたところ、原因がわからず、結局3日位かけたのではないかと思います。
では、現象と原因と対策を
【現象】
ListViewに表示した最初の明細のみ、CheckBox、RadioButton、Buttonが効かない。
正確に書くと、Viewの位置がずれているような感じ。
CheckBoxをタッチしても、リスナーが実行されず、隣のTextViewをタッチすると、CheckBoxとTextViewのリスナーが同時に実行されるみたいな動きだった。
この現象は、先頭のViewでしかおこらず、スクロールした場合、現象のおこった明細を再利用した明細が同じようになった。
【環境】
Android 最小8 ターゲット18
Adapterはカスタムしていた。
レイアウトはRelativeLayoutでディテールにListViewを指定している。
ディティールはLinearLayoutでorientationはvertical
【原因】
Activityから渡したArrayListの明細数以上にgetViewが呼ばれている。
こんな感じ。
getView:265]0 <- この数字がポジション。
08-16 09:09:26.132: I/LogUtil(3743): [SDListAdapter#getView:265]0
08-16 09:09:26.136: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]0
08-16 09:09:26.136: I/LogUtil(3743): [SDListAdapter#getView:265]1
08-16 09:09:26.136: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]1
08-16 09:09:26.140: I/LogUtil(3743): [SDListAdapter#getView:265]2
08-16 09:09:26.140: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]2
08-16 09:09:26.140: I/LogUtil(3743): [SDListAdapter#getView:265]3
08-16 09:09:26.140: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]3
08-16 09:09:26.140: I/LogUtil(3743): [SDListAdapter#getView:265]4
08-16 09:09:26.144: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]4
08-16 09:09:26.144: I/LogUtil(3743): [SDListAdapter#getView:265]5
08-16 09:09:26.144: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]5
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getView:265]0
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]0
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getView:265]1
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]1
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getView:265]2
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]2
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getView:265]3
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]3
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getView:265]4
08-16 09:09:26.152: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]4
08-16 09:09:26.152: I/LogUtil(3743): [SDListAdapter#getView:265]5
08-16 09:09:26.152: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]5
08-16 09:09:26.152: I/LogUtil(3743): [SDListAdapter#getView:265]0
08-16 09:09:26.152: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]0
08-16 09:09:26.164: I/LogUtil(3743): [SDListAdapter#getView:265]1
08-16 09:09:26.168: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]1
08-16 09:09:26.168: I/LogUtil(3743): [SDListAdapter#getView:265]2
08-16 09:09:26.172: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]2
08-16 09:09:26.172: I/LogUtil(3743): [SDListAdapter#getView:265]3
08-16 09:09:26.172: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]3
08-16 09:09:26.176: I/LogUtil(3743): [SDListAdapter#getView:265]4
08-16 09:09:26.176: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]4
08-16 09:09:26.180: I/LogUtil(3743): [SDListAdapter#getView:265]5
08-16 09:09:26.180: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]5
それだけなら、実害はないかと思ったんだけど、AdapterのgetViewでconvertViewがnullでない場合、Viewを使い回すが、最初の呼び出しにもかかわらず、同一ポジションが複数回呼ばれた場合、Viewを使い回すになり、その時の最初の明細のみ、この現象がおこっているとわかった。(なぜ現象が発生するかまではわからなかった)
なので、使い回しをせずに、毎回inflateするとその現象は起きない。
ただ、それだとレスポンスが悪化するので、複数回呼ばれる原因を確認したところ、AbsListViewで高さのサイズ計算が関係しているみたいだったので、ListViewのレイアウトを確認すると、layout_heightがwrap_contentだった。
この現象がRelativeLayoutのみで発生するのか、LinearLayoutでも発生
のか、までは確認していない。
【対策】
まず、layout_heightをmatch_parentに変えたところ、getViewが複数回呼ばれなくなった。
また、layout_height=“0dp”にして、layout_weight=“1”でも複数回呼ばれない事を確認した。
いや、これはほんとに時間かかりました。最初にボタンが効かなくなる現象を確認したのは今年の2月位で、この時は毎回inflateする事で逃げたのですが、結構多いデータを実機で試したところ、かなり遅かったので、本腰入れて調べ始めて、3日位かかったかと思います。Adapterだけではなく、ListViewもカスタムしていた為、どの機能で発生しているを見つけるまでが大変でした。
getViewが複数回呼び出されている現象がわかってからも、なぜ呼び出されるかの原因は見つける事ができず、幸い、メニューだけはなぜか複数回呼ばれていないので、その機能と発生する機能との違いを順番にソースを書き換えて動作確認し、レイアウトを変更すると発生する事がわかり、それで初めてListViewのlayout_heightが違う事に気づきました。
見た目は正常に動作していて、かつ同一ロジックの明細で一部だけにバグが出ると、見つけるのは、ほんとに時間かかります。
最後に、
また客先常駐の仕事が入り、今回は半年以上続きそうなので、ゆっくりアプリを作り続けます。
最初は実害がないと思ったので放置していた事もあったのですが、レスポンスが悪いので改善しようとしたところ、原因がわからず、結局3日位かけたのではないかと思います。
では、現象と原因と対策を
【現象】
ListViewに表示した最初の明細のみ、CheckBox、RadioButton、Buttonが効かない。
正確に書くと、Viewの位置がずれているような感じ。
CheckBoxをタッチしても、リスナーが実行されず、隣のTextViewをタッチすると、CheckBoxとTextViewのリスナーが同時に実行されるみたいな動きだった。
この現象は、先頭のViewでしかおこらず、スクロールした場合、現象のおこった明細を再利用した明細が同じようになった。
【環境】
Android 最小8 ターゲット18
Adapterはカスタムしていた。
レイアウトはRelativeLayoutでディテールにListViewを指定している。
ディティールはLinearLayoutでorientationはvertical
【原因】
Activityから渡したArrayListの明細数以上にgetViewが呼ばれている。
こんな感じ。
getView:265]0 <- この数字がポジション。
08-16 09:09:26.132: I/LogUtil(3743): [SDListAdapter#getView:265]0
08-16 09:09:26.136: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]0
08-16 09:09:26.136: I/LogUtil(3743): [SDListAdapter#getView:265]1
08-16 09:09:26.136: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]1
08-16 09:09:26.140: I/LogUtil(3743): [SDListAdapter#getView:265]2
08-16 09:09:26.140: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]2
08-16 09:09:26.140: I/LogUtil(3743): [SDListAdapter#getView:265]3
08-16 09:09:26.140: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]3
08-16 09:09:26.140: I/LogUtil(3743): [SDListAdapter#getView:265]4
08-16 09:09:26.144: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]4
08-16 09:09:26.144: I/LogUtil(3743): [SDListAdapter#getView:265]5
08-16 09:09:26.144: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]5
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getView:265]0
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]0
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getView:265]1
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]1
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getView:265]2
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]2
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getView:265]3
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]3
08-16 09:09:26.148: I/LogUtil(3743): [SDListAdapter#getView:265]4
08-16 09:09:26.152: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]4
08-16 09:09:26.152: I/LogUtil(3743): [SDListAdapter#getView:265]5
08-16 09:09:26.152: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]5
08-16 09:09:26.152: I/LogUtil(3743): [SDListAdapter#getView:265]0
08-16 09:09:26.152: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]0
08-16 09:09:26.164: I/LogUtil(3743): [SDListAdapter#getView:265]1
08-16 09:09:26.168: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]1
08-16 09:09:26.168: I/LogUtil(3743): [SDListAdapter#getView:265]2
08-16 09:09:26.172: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]2
08-16 09:09:26.172: I/LogUtil(3743): [SDListAdapter#getView:265]3
08-16 09:09:26.172: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]3
08-16 09:09:26.176: I/LogUtil(3743): [SDListAdapter#getView:265]4
08-16 09:09:26.176: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]4
08-16 09:09:26.180: I/LogUtil(3743): [SDListAdapter#getView:265]5
08-16 09:09:26.180: I/LogUtil(3743): [SDListAdapter#getViewLocal:291]5
それだけなら、実害はないかと思ったんだけど、AdapterのgetViewでconvertViewがnullでない場合、Viewを使い回すが、最初の呼び出しにもかかわらず、同一ポジションが複数回呼ばれた場合、Viewを使い回すになり、その時の最初の明細のみ、この現象がおこっているとわかった。(なぜ現象が発生するかまではわからなかった)
なので、使い回しをせずに、毎回inflateするとその現象は起きない。
ただ、それだとレスポンスが悪化するので、複数回呼ばれる原因を確認したところ、AbsListViewで高さのサイズ計算が関係しているみたいだったので、ListViewのレイアウトを確認すると、layout_heightがwrap_contentだった。
この現象がRelativeLayoutのみで発生するのか、LinearLayoutでも発生
のか、までは確認していない。
【対策】
まず、layout_heightをmatch_parentに変えたところ、getViewが複数回呼ばれなくなった。
また、layout_height=“0dp”にして、layout_weight=“1”でも複数回呼ばれない事を確認した。
いや、これはほんとに時間かかりました。最初にボタンが効かなくなる現象を確認したのは今年の2月位で、この時は毎回inflateする事で逃げたのですが、結構多いデータを実機で試したところ、かなり遅かったので、本腰入れて調べ始めて、3日位かかったかと思います。Adapterだけではなく、ListViewもカスタムしていた為、どの機能で発生しているを見つけるまでが大変でした。
getViewが複数回呼び出されている現象がわかってからも、なぜ呼び出されるかの原因は見つける事ができず、幸い、メニューだけはなぜか複数回呼ばれていないので、その機能と発生する機能との違いを順番にソースを書き換えて動作確認し、レイアウトを変更すると発生する事がわかり、それで初めてListViewのlayout_heightが違う事に気づきました。
見た目は正常に動作していて、かつ同一ロジックの明細で一部だけにバグが出ると、見つけるのは、ほんとに時間かかります。
最後に、
また客先常駐の仕事が入り、今回は半年以上続きそうなので、ゆっくりアプリを作り続けます。
【このカテゴリーの最新記事】
-
no image
-
no image
-
no image
-
no image
-
no image
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
https://fanblogs.jp/tb/4067500
※ブログオーナーが承認したトラックバックのみ表示されます。
この記事へのトラックバック