in 未分類

【android】ListViewで追加してる途中でエラーが出る・・・。

※この内容は間違っています。

基本的に以下のエラーが出るときはメインスレッド以外からListViewの更新をしている可能性があります。
詳しくはListView、ArrayAdapterの良くあるエラー
を参照してください。
1014/3/25追記

いろいろ癖のあるListViewだけど、どう見てもバグな感じがする部分をみつけた。
ListView#LayoutChldren()で

if (mItemCount == 0) {
	resetList();
	invokeOnItemScrollListener();
	return;
} else if (mItemCount != mAdapter.getCount()) {
	throw new IllegalStateException("The content of the adapter has changed but "
			+ "ListView did not receive a notification. Make sure the content of "
			+ "your adapter is not modified from a background thread, but only "
			+ "from the UI thread. [in ListView(" + getId() + ", " + getClass() 
			+ ") with Adapter(" + mAdapter.getClass() + ")]");
}

ってところがある。
問題は

mItemCount != mAdapter.getCount()

ってところ。
mItemCountはListViewで保持しているListの数で
mAdapter.getCount()はadapterが保持しているリストの数。
これを比較して違ったらエラーを吐いて終了。
adapterの要素の数とListの数が違ったらダメってだけで普通は問題ない。

でも、ArrayAdapter#add(Object)をしてる間にLayoutChldren()が呼ばれると問題が発生する。
ArrayAdapter#add(Object)ではArrayAdapter内のArrayListにaddして
mNotifyOnChangeがtureならArrayAdapter#notifyDataSetChanged()をしてる。
mNotifyOnChangeはArrayAdapter#setNotifyOnChange()で変更できる。
で問題はここから
ArrayAdapter#notifyDataSetChanged()ではmItemCount=mAdapter.getCount()で要素の数を更新している。
つまり、
ArrayAdapter内のArrayListにaddしてnotifyDataSetChanged()でmItemCount=mAdapter.getCount()をするまでの間に
LayoutChldren()が呼ばれるとArrayListにはaddされちゃってるので要素が多くなってる。でもmItemCountは、まだ更新されてないから
エラーになっちゃうわけである。

これバグだよね?
ついでにinsertもだめ・・・。

ArrayAdapter#add()の部分
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.1_r1/android/widget/ArrayAdapter.java#ArrayAdapter.add%28java.lang.Object%29

ListView#layoutChildren()の部分
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2.1_r1/android/widget/ListView.java#ListView.layoutChildren%28%29

この辺見るとわかると思う。
このエラー出ないようにするには例えばadapter.getCount()で返す数字を直接ArrayList.size()にするのをやめるためOverrideするのがいいとおもう。


	private int count=0;
	
	@Override
	public int getCount(){
		return count;
	}
	
	@Override
	public void notifyDataSetChanged(){
		super.notifyDataSetChanged();
		count=Items.size();
	}

こんな感じにしておけばとりあえず追加してもnotifyDataSetChanged()されるまで数が増えないから少しはマシかも。


2 Comments

  1. hoge@fuga.com 2013年4月2日 Reply
  2. in_dow 2013年10月31日 Reply

Add a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Anti-spam image