为什么不能实时更新c listview 实时刷新

ListView的动态刷新问题——用notifyDataSetChanged没作用 - 推酷
ListView的动态刷新问题——用notifyDataSetChanged没作用
也许很多开发的朋友,尤其是Android初学者,在动态刷新ListView时,使用notifyDataSetChanged并没有起到作用。有时会被困扰得很痛苦。
其实,在使用notifyDataSetChanged过程中,还是有细节需要注意的。举个例子:
我的ListView使用的数据源是来自ArrayList。通常我们的做法是创建一个已经有我们想要提供给ListView的数据的ArrayList,例如:
ArrayList&Integer& list
= new ArrayList&Interger&;
list.add(1);
这里我们的list已经是指向了一个堆内存上了。接着我们想要改变list中的数据,而这个时候,就需要注意了,举个例子:我们在代码中有另外一个ArrayList叫做newlist,它是使用下面代码创建出来的:
ArrayList&Integer& newlist
= new ArrayList&Interger&;
list.add(2);
这个时候,newlist指向的是一个和list指向不同的堆内存,这个时候,我们直接用list = newlist来把newlist的数据交给list,在这里,实际上只是把list的指向改变了,让它也指向newlist指向的那个内存。那么这个时候我们再调用notifyDataSetChanged这个方法来通知listview更新数据就起不了任何作用了,原因很简单,就是list的指向已经改变,而调用notifyDataSetChanged会去检查原来list指向的数据是否变化,但是这时的list已经不是原来的list了,所以它无法判断,只能不作出响应了。那么,这个问题的解决方法是直接在原来的list上面更改数据,可以使用下面的代码来操作:
list.clear();
list.addAll(newlist);
adapter.notifyDataSetChanged();
这样,list的指向就不会改变,它还是指向原来那块内存,这样调用notifyDataSetChanged()就可以起作用了。
总结:在这里的重点就是要注意在开始时传给ListView的list指向不能被改变,需要从始至终指向同一个内存,这样调用notifyDataSetChanged后就能够检测到list的数据变化,从而触发ListView的重新绘制了!
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致3168人阅读
Android(41)
最近做数独Android程序,在选择数独题目时用到了ListActivity,ListActivity比较特别,在从一个Activity跳转到ListActivity时,结果报了异常,
上网查了下,原来虽然listactivity是Activity子类,但listactivity必须与布局文件(ListView)配合起来才能正常跳转,且ListView中android:id必须为@id/android:list。
使用了ListActivity类后,如果整个屏幕上只需显示一个列表,我们甚至可以把setContentView一行注释掉,不用定义列表的XML说明文件。因为ListActivity类已经默认绑定了一个ListView(列表视图)界面组件。
Sudoku_list.xml文件如下:
&?xml version=&1.0& encoding=&utf-8&?&
&LinearLayout xmlns:android=&/apk/res/android&
android:orientation=&vertical&
android:layout_width=&fill_parent&
android:layout_height=&fill_parent&&
&ListView android:id=&@id/android:list&
android:layout_width=&fill_parent&
android:layout_height=&fill_parent&/&
&/LinearLayout&如果使用自定义的list的话,我们还可以对每个list_item进行修改,设计出相应的界面。这时候需要定义sudoku_list_item.xmllayout文件
&?xml version=&1.0& encoding=&utf-8&?&
&RelativeLayout xmlns:android=&/apk/res/android&
android:orientation=&vertical&
android:layout_width=&fill_parent&
android:layout_height=&wrap_content&
android:padding=&4sp&&
android:id=&@+id/puzzle_id&
android:text=&@string/puzzle&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_alignParentTop=&true&
android:layout_alignParentLeft=&true&
android:textAppearance=&?android:attr/textAppearanceMedium&/&
android:id=&@+id/rowId&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_alignParentTop=&true&
android:layout_toRightOf=&@id/puzzle_id&
android:textAppearance=&?android:attr/textAppearanceMedium&
android:id=&@+id/state&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_alignParentTop=&true&
android:layout_toRightOf=&@id/rowId&
android:textAppearance=&?android:attr/textAppearanceMedium&
&TextView android:id=&@+id/past_time&
android:text=&@string/past_time&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_below=&@id/state&
android:layout_marginLeft=&4sp&
android:layout_marginRight=&8sp&
android:textAppearance=&?android:attr/textAppearanceMedium&/&
android:id=&@+id/time&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_toRightOf=&@id/past_time&
android:layout_alignTop=&@id/past_time&
android:layout_marginLeft=&4sp&
android:layout_marginRight=&8sp&
android:textAppearance=&?android:attr/textAppearanceMedium&
android:id=&@+id/best_time&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_alignParentTop=&true&
android:layout_alignParentRight=&true&
android:layout_marginLeft=&4sp&
android:layout_marginRight=&8sp&
android:textAppearance=&?android:attr/textAppearanceMedium&
&TextView android:id=&@+id/best&
android:text=&@string/best_time&
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:layout_toLeftOf=&@id/best_time&
android:layout_marginLeft=&4sp&
android:layout_marginRight=&8sp&
android:textAppearance=&?android:attr/textAppearanceMedium&/&
&/RelativeLayout&
结果,一运行虽然能进去,但是每次运行后数据库里面的数据文件就会改变,我希望ListActivity的每个list_item也会随着改变,不幸的是list_item一直没有变化,只有当ListActivity重新onCreate()调用数据库时才能显示相应的改变。
上网查了下,有的说用handler启动一个新的线程对ListActivity进行实时更新,效果都不好。
最后我选择用SimpleCursorAdapter,完美解决实时更新问题,并且对于数据库很适合使用
public SimpleCursorAdapter (Context context, int layout, Cursor c, String[] from, int[] to)
第一个参数是当前Context提供了关于应用环境全局信息的接口,第二个参数是定义的list_item.xml文件,第三个参数是数据库的游标,如果还没有应用的话可以用null代替,第四个参数是数据库列表的每列的名称,第五个参数是对应的每个Item所要展示的TextView的id,并且只能是TextView,与第四个参数的对应的数据库里面的信息相对应。
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.sudoku_list);
//setListAdapter(new ArrayAdapter&String&(this,
android.R.layout.simple_list_item_1, puz));
diff = getIntent().getIntExtra(Game.KEY_DIFFICULTY,
Game.DIFFICULTY_KIDS);
db = new DBAdapter(getApplicationContext());
adapter = new SimpleCursorAdapter(this, R.layout.sudoku_list_item,
null, new String[]{DBAdapter.KEY_ROWID, DBAdapter.KEY_IS_COMPLETE,
DBAdapter.KEY_COST_TIME, DBAdapter.KEY_BEST_TIME},
new int[]{R.id.rowId, R.id.state, R.id.time, R.id.best_time});
adapter.setViewBinder(new SudokuListViewBinder(this));
updateList();
setListAdapter(adapter);
}updateList方法用于实时更新所有的list
private void updateList(){
if (mCursor != null) {
stopManagingCursor(mCursor);
mCursor = getSudokuList();
//updateInfo(mCursor);
startManagingCursor(mCursor);
adapter.changeCursor(mCursor);
}最后一运行,虽然可以实时更新,但是因为SimpleCursorAdapter里面每个Item里面的TextView有一个是表示这个数独谜题所在的id,所以在程序里面显示的就是该谜题的id,因为第二个等级难度的数独题目的id是接在第一个等级数独题目的后面,也就是说,第二个等级的第一个题目本来应该显示Puzzle1,可是它显示的是Puzzle65(每个等级有64道题),SimpleCursorAdapter可以很好的解决ListActivity的实时更新问题,可是它显示的就是游标对应的数据不能更改,最后运行效果如下
相应的问题也有很多,比如数据库里面有个数据是isComplete,它是long型值,如果是0,就输出playing,如果是1,就输出solved。
最后参考了些开源的代码,找到解决办法了,使用了setViewBinder方法
public void setViewBinder (SimpleCursorAdapter.ViewBinder viewBinder)
在程序里面定义了一个内部类,实现了ViewBinder接口,重写public boolean setViewValue(View view, Cursor c, int columnIndex)方法
private static class SudokuListViewBinder implements ViewBinder {
private Context mC
public SudokuListViewBinder(Context context) {
mContext =
public boolean setViewValue(View view, Cursor c, int columnIndex) {
TextView label =
switch (view.getId()) {
case R.id.rowId:
int id = c.getInt(c.getColumnIndex(DBAdapter.KEY_ROWID));
int puzzle = id - diff * NUM + 1;
label = (TextView)
label.setText(puzzle + &&);
// TODO: still can be faster, I don't have to call initCollection and read notes
case R.id.state:
label = ((TextView) view);
long state = c.getLong(c.getColumnIndex(DBAdapter.KEY_IS_COMPLETE));
label.setText(state == 1 ? & & + mContext.getString(R.string.Solved) :
& & + mContext.getString(R.string.playing));
case R.id.time:
String cost_time = mGameTimeFormatter.format(
c.getLong(c.getColumnIndex(DBAdapter.KEY_COST_TIME)));
label = ((TextView) view);
if(cost_time.equals(&00:00&)){
label.setText(mContext.getString(R.string.default_time));
label.setText(cost_time);
case R.id.best_time:
String bestTime = mGameTimeFormatter.format(
c.getLong(c.getColumnIndex(DBAdapter.KEY_BEST_TIME)));
label = ((TextView) view);
if(bestTime.equals(&00:00&)){
label.setText(mContext.getString(R.string.default_time));
label.setText(bestTime);
}最后问题圆满解决,运行效果
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:180199次
积分:2500
积分:2500
排名:第10729名
原创:60篇
转载:10篇
评论:83条
(5)(3)(2)(5)(2)(1)(3)(1)(4)(3)(1)(1)(4)(1)(4)(2)(6)(10)(3)(1)(1)(3)(1)(1)(1)(1)今天看啥 热点:
PullToRefreshListView自动刷新api,pullrefreshlistview
百度了几个小时居然没看到有人知道这api,找得我蛋疼。
只要上这个代码就能触发自动下拉的事件。例如第一次进入界面时候,该PullToRefreshListView自动在刷新。
listView.post(new Runnable() {
&&&@Override
&&&public void run() {
&&&&listView.setPullDownRefreshing(100);//延迟执行的下拉时间(毫秒)
相关搜索:
相关阅读:
相关频道:
Android教程最近更新android listview adapter不能及时更新的问题_百度知道

我要回帖

更多关于 listview实时刷新数据 的文章

 

随机推荐