mi wlan adapter驱动.notifyDataSetChanged没有更新,谁遇到过

11621人阅读
android使用notifyDataSetChanged()方法,发现adapter的数据更新了,但是ListView的内容没有更新?
查阅如下网站解决方案都没有解决:
后来冷静一想,我遇到这个问题的情景跟他们的有所区别:
我的问题是从另个界面跳转回来后,再调用apater的notifyDataSetChanged()方法时失效,adapter的数据更新了,
但listview显示的内容并没有改变。
针对这个问题的解决方案是:
在Activity的onResume()方法中将adaper和listView重新再绑定一次。
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
在此记录下,备用。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:411960次
积分:4774
积分:4774
排名:第2568名
原创:105篇
评论:82条
(1)(1)(1)(1)(5)(4)(4)(2)(4)(4)(4)(2)(2)(7)(6)(6)(11)(9)(10)(8)(8)(9)Android记录15--关于ListView中adapter调用notifyDataSetChanged无效的原因
Android记录15--关于ListView中adapter调用notifyDataSetChanged无效的原因
日 开发记录
话说这个问题已经困扰我很久了,一直找不到原因,我以为只要数据变了,调用adapter的notifyDataSetChanged就会更新列表,最近在做微博帐号管理这一块,想着动态更新列表,数据是变了,但就是没有把更新的数据显示出来。为什么是这样,以下是我总结的一些原因:
1、数据源没有更新,调用notifyDataSetChanged无效。
2、数据源更新了,但是它指向新的引用,调用notifyDataSetChanged无效。
3、数据源更新了,但是adpter没有收到消息通知,无法动态更新列表。
我遇到的问题的原因是第2条,数据源更新了,但它指向新的引用,这样说很抽象,拿具体例子来说吧,
我们在显示ListView数据的时候,首先需要一个数据适配器,叫做adapter的东西
1、定义两个适配器:
1个是新浪微博帐号的适配器,另一个是腾讯微博帐号的适配器
public static AccountListAdapter sinaAccountA
public static AccountListAdapter tencentAccountA
2、定义数据源
userInfos存放的是所有帐号的数据,sinaUsers存放的是新浪帐号的数据,tencentUsers存放的是腾讯帐号的数据
public static List userI
private static List sinaU
private static List tencentU
3、获取数据
// 获取帮助对象
dataHelper = DataBaseContext.getInstance(mContext);
// 获取用户列表
userInfos = dataHelper.getUserList(true);
setListAdapter();
private void setListAdapter() {
// 获得新浪用户和腾讯用户的列表
getSinaUsers();
getTencentUsers();
if (userInfos.size() == 0) {
Toast.makeText(mContext, "您还没有添加过账号哦", Toast.LENGTH_LONG).show();
sinaAccountAdapter = new AccountListAdapter(AccountManage.this,
sinaUsers);
tencentAccountAdapter = new AccountListAdapter(AccountManage.this,
tencentUsers);
accountListView.setAdapter(sinaAccountAdapter);
从setListAdapter这个方法中,我们可以看到,sinaAccountAdapter的数据源是sinaUsers,而tencentAccountAdapter的数据源是tencentUsers,他们分别通过getSinaUsers()、getTencentUser()方法得到
// 获得新浪用户
private static List getSinaUsers() {
sinaUsers = new ArrayList();
for (UserInfo userInfo : userInfos) {
if (userInfo.getType() == SINA) {
sinaUsers.add(userInfo);
return sinaU
// 获得腾讯用户
private static List getTencentUsers() {
tencentUsers = new ArrayList();
for (UserInfo userInfo : userInfos) {
if (userInfo.getType() == TENCENT) {
tencentUsers.add(userInfo);
return tencentU
我现在要定义动态更新两个帐号列表的方法
public static void updateSinaUserList() {
// 获取数据库用户列表
userInfos = dataHelper.getUserList(true);
List infos = new ArrayList();
for (UserInfo userInfo : userInfos) {
if (userInfo.getType() == SINA) {
infos.add(userInfo);
sinaUsers.clear();
sinaUsers.addAll(infos);
// 更新列表
sinaAccountAdapter.notifyDataSetChanged();
public static void updateTencentUserList() {
// 获取数据库用户列表
userInfos = dataHelper.getUserList(true);
List infos = new ArrayList();
for (UserInfo userInfo : userInfos) {
if (userInfo.getType() == TENCENT) {
infos.add(userInfo);
tencentUsers.clear();
tencentUsers.addAll(infos);
tencentAccountAdapter.notifyDataSetChanged();
以上的两个方法是可以实现动态更新列表的,因为它是同一个数据源,并没有指向新的引用,我之前是直接调用getSinaUsers()和getTencentUsers()方法,这相当于重新new了一个List,并不是原来的数据源,所以无论怎么调用notifyDataSetChanged都是无效的。
您对本文章有什么意见或着疑问吗?请到您的关注和建议是我们前行的参考和动力&&
您的浏览器不支持嵌入式框架,或者当前配置为不显示嵌入式框架。使用SimpleAdapter,调用notifyDataSetChanged的方法刷新页面的问题
[问题点数:50分,无满意结帖,结帖人shinezqm725]
使用SimpleAdapter,调用notifyDataSetChanged的方法刷新页面的问题
[问题点数:50分,无满意结帖,结帖人shinezqm725]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
2015年5月 扩充话题大版内专家分月排行榜第三
2014年6月 移动开发大版内专家分月排行榜第一2014年3月 移动开发大版内专家分月排行榜第一
2014年11月 移动开发大版内专家分月排行榜第二2014年4月 移动开发大版内专家分月排行榜第二2014年2月 移动开发大版内专家分月排行榜第二
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。& & 导师安排我做一个小项目,其中涉及到利用Adapter作为ListView的适配器,为ListView提供数据。选中某一项后,要让这一项变成选中状态,也就是背景图片要换一下。下面我就用一个小例子来模拟。重点不在于实现,而是了解Adapter中notifyDataSetChanged()背后的运行机制。
& & 我们先做一个小Demo(文中涉及的Demo在文章末尾),功能是选中某一项后,背景颜色会变红。代码非常简单,这里就不解释了。值得注意的是,当我们需要ListView进行刷新的时候,我们需要调用Adapter.notifyDataSetChanged()来让界面刷新。
1 public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView main_list = (ListView)this.findViewById(R.id.main_list);
MyArrayAdapter mArrayList=new MyArrayAdapter(this,R.layout.list_item,getData());
main_list.setAdapter(mArrayList);
main_list.setOnItemClickListener(mArrayList);
private String[] getData() {
return new String[]{"测试数据1","测试数据2","测试数据3","测试数据4"};
适配器MyArrayAdapter代码:
1 public class MyArrayAdapter extends ArrayAdapter&String& implements
OnItemClickListener {
private int itemC
public MyArrayAdapter(Context context, int textViewResourceId,
String[] objects) {
super(context,
textViewResourceId, objects);
11 @Override
12 public View getView(int position, View convertView, ViewGroup parent) {
convertView=super.getView(position, convertView, parent);
//如果是被点击的项,变换颜色
if (position==this.itemClicked) {
convertView.setBackgroundColor(Color.RED);
convertView.setBackgroundColor(Color.WHITE);
return convertV
public void onItemClick(AdapterView&?& parent, View view, int position,
long id) {
//设置某项被点击
itemClicked=
this.notifyDataSetChanged();
下面就让我们跟进去MyArrayAdapter.notifyDataSetChange()中看看。在本文中,我所查看的Android源代码是4.4.0的,不同版本可能有所出入。
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
mNotifyOnChange = true;
源代码就简单两句话,那么继续看看super是什么?
public class ArrayAdapter&T& extends BaseAdapter implements Filterable
从类的声明中,父类就是ArrayAdapter,而ArrayList的父类是BaseAdapter。我们跟进BaseAdapter中看看。
1 public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
//...省略不必要的代码
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
public void notifyDataSetInvalidated() {
mDataSetObservable.notifyInvalidated();
//...省略不必要的代码
我们发现其实就是DataSetObservable这个对象在发生作用,但是DataSetObservable这个对象估计就是一个简单的观察者的实现,Android框架的编写者不大可能将业务逻辑放在这里面,不过我们还是要确认是不是跟我们所想的一样。
1 public class DataSetObservable extends Observable&DataSetObserver& {
* Invokes onChanged on each observer. Called when the data set being observed has
* changed, and which when read contains the new state of the data.
public void notifyChanged() {
synchronized(mObservers) {
for (DataSetObserver observer : mObservers) {
observer.onChanged();
* Invokes onInvalidated on each observer. Called when the data set being monitored
* has changed such that it is no longer valid.
public void notifyInvalidated() {
synchronized (mObservers) {
for (DataSetObserver observer : mObservers) {
observer.onInvalidated();
果然,跟预想的一样,它只是简单地调用了绑定在它身上的回调接口。那么BaseAdapter.notifyDataSetChange()的接口具体是在哪里绑定的呢?很有可能在构造函数中绑定,我们跟进ArrayListAdapter看看。
public ArrayAdapter(Context context, int textViewResourceId, List&T& objects) {
init(context, textViewResourceId, 0, objects);
private void init(Context context, int resource, int textViewResourceId, List&T& objects) {
mContext =
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mResource = mDropDownResource =
mObjects =
mFieldId = textViewResourceId;
ArrayListAdapter中有很多构造函数,但是几经辗转全部都会转到init()函数中,很遗憾,我们扑空了。那么还在哪里可能绑定notifyDataSetChange()回调函数呢?其实从MainActivity中Adapter的初始化过程中,基本上只能锁定在MainActivity第十行中setAdapter函数中。接下去看看 public void setAdapter(ListAdapter adapter)这个函数。&
public void setAdapter(ListAdapter adapter) {
if (null != mAdapter) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
resetList();
mRecycler.clear();
if (mHeaderViewInfos.size() & 0|| mFooterViewInfos.size() & 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
mAdapter =
mOldSelectedPosition = INVALID_POSITION;
mOldSelectedRowId = INVALID_ROW_ID;
if (mAdapter != null) {
mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
mOldItemCount = mItemC
mItemCount = mAdapter.getCount();
checkFocus();
mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);
mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());
if (mStackFromBottom) {
position = lookForSelectablePosition(mItemCount - 1, false);
position = lookForSelectablePosition(0, true);
setSelectedPositionInt(position);
setNextSelectedPositionInt(position);
if (mItemCount == 0) {
// Nothing selected
checkSelectionChanged();
if (mChoiceMode != CHOICE_MODE_NONE &&
mAdapter.hasStableIds() &&
mCheckedIdStates == null) {
mCheckedIdStates = new LongSparseArray&Boolean&();
mAreAllItemsSelectable = true;
checkFocus();
// Nothing selected
checkSelectionChanged();
if (mCheckStates != null) {
mCheckStates.clear();
if (mCheckedIdStates != null) {
mCheckedIdStates.clear();
requestLayout();
setAdapter(...)这个函数有点长,不过我们只需要关注跟notifiDataSetChange()有关的实现,也就是第23、24行。不过这里另一个值得关注的点就是第63行,requestLayout()这个函数,它主要就是用来刷新界面,让界面重新绘制的。在23,、24行,绑定了一个AdapterDataSetObserver对象,下面我们就跟进去看看。从前面DataSetObservable的实现中,我们知道了它在notifyDataSetChange()的时候会调用DataSetObserver的onChange()。
class AdapterDataSetObserver extends DataSetObserver
private Parcelable mInstanceState = null;
AdapterDataSetObserver() {
public void onChanged() { mDataChanged = true;
mOldItemCount = mItemC
mItemCount = getAdapter().getCount();
if ((getAdapter().hasStableIds()) && (mInstanceState != null) && (mOldItemCount == 0) && (mItemCount & 0))
onRestoreInstanceState(mInstanceState);
mInstanceState = null;
rememberSyncState();
checkFocus();
requestLayout();
//...省略不必要代码
终于,在第19行,我们看见了requestLayout(),它就是用来重绘界面的,它在ViewRootImpl.java中有具体的实现。
public void requestLayout() {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
关于scheduleTraversals()的实现,涉及到Android中View的绘制流程,感兴趣的可以看看《》。
& & 到了这里,我们就清楚了notifyDataSetChange()背后的实现机制了,在不知不觉之间Android框架帮我们干了很多事情,不过需要提醒的时,每一次notifyDataSetChange()都会引起界面的重绘。当需要修改界面上View的相关属性的时候,最后先设置完成再调用notifyDataSetChange()来重绘界面。
阅读(...) 评论()

我要回帖

更多关于 adapter 的文章

 

随机推荐