アフィリエイト広告を利用しています
ファン
<< 2015年08月 >>
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
最新記事
カテゴリアーカイブ
android(10)
プロフィール
びーまさんの画像
びーま
50をこえて、androidアプリを作り始めた変わり者です。 オペレータ、PG、SE、PM、コンサルと全て経験はしています(笑)。 個人的に一人で設計して、一人で開発して、納得できるシステムを作ってみたかったので、始めました。 まあ、コスト無視の趣味だからできる訳なんで、妥協せずアプリを作っています。 なので、開発期間は・・・(汗)。
ブログ
プロフィール

広告

posted by fanblog

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が違う事に気づきました。

見た目は正常に動作していて、かつ同一ロジックの明細で一部だけにバグが出ると、見つけるのは、ほんとに時間かかります。

最後に、

また客先常駐の仕事が入り、今回は半年以上続きそうなので、ゆっくりアプリを作り続けます。
posted by びーま at 10:06| Comment(0) | TrackBack(0) | android
この記事へのコメント
コメントを書く

お名前:

メールアドレス:


ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバックURL
https://fanblogs.jp/tb/4067500
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック
検索
最新コメント
タグクラウド
×

この広告は30日以上新しい記事の更新がないブログに表示されております。