本人在开发中,通过联网获取新闻列表,会遇到需要动态增加listview的条目项的问题。我们一般都是通过adapter绑定一个数据源,以SimpleAdapter为例
即
SimpleAdapter adapter = new SimpleAdapter(this.mContext, mStrings,
R.layout.info_list_item, new String[] { "heading", "date" },
new int[] { R.id.infoheading, R.id.date });
其中mStrings是一个ArrayList,在尾部需要加载更多时,采用联网获取新条目然后加到旧的listview中去。然后在主线程(更多时候是Handler类里)中使用adapter.notifyDataSetChanged()通知ListView数据源有改动,需要更新。
但是有时候在使用过程中却出现notify之后ListView却没有相应更新。
解决方案有2种:
1.重新初始化adapter,即在完成数据的添加后,在主线程(Handler类)中重新初始化并绑定数据:
adapter = new SimpleAdapter(this.mContext, mStrings, R.layout.info_list_item, new String[] { "heading", "date" },
new int[] { R.id.infoheading, R.id.date });
mListView.setAdapter(adapter);
但是这样有一个问题,就是如果我在ListView的尾部添加了数据,重新setAdapter之后,视图中当前显示的条目会立马回到最顶的一条,这在用户已经下滑到下面之后是一个不太好的体验。
2.另一种方案就是检查你的代码,找到导致notify方法失效的原因。检查是否在更新mString这个ArrayList时直接使用了mStrings = newString这样的代码。这个代码看上去确实更改了mString中的数据,但却产生了一个新的问题,也就是导致notify方法失效的问题:当你初始化mStrings方法即ArrayList<<>> mStrings = new ArrayList<<>>()时,新建了一个ArrayList对象Obj1并将mStrings指向了它,同时Adapter初始化时也就将Adapter的数据源指向了Obj1。而在你尝试动态更改mStrings时使用了mStrings = newStrings,也就是将mStrings的指针指向了新的newStrings,必然不再是Obj1了。此时你觉得更改了mStrings的值,但事实上并未更改到adapter绑定的数据源里的数据。
弄明白了这点,只需要找到你的代码中所有采用指向新对象方式更改mStrings的值,改为
mStrings.clear();
mStrings.addAll(newStrings);
就可以了。在开发过程中,也应尽量使用mStrings.add(),remove,clear等方法,以保证你更改的数据源和adapter绑定的对象为同一个。