您的位置:首页 > 其它

ListView中使用自定义Adapter及时更xin

2014-05-26 00:34 253 查看
在项目中,遇到不能ListView及时更新的问题。写了一个demo,其中也遇到一些问题,一并写出来。好吧,上代码:

public class PersonAdapter extends BaseAdapter {
private ArrayList<PersonBean> mList;
private Context mContext;

public PersonAdapter(ArrayList<PersonBean> list, Context context) {
mList = list;
mContext = context;
}

public void refresh(ArrayList<PersonBean> list) {
mList = list;
notifyDataSetChanged();
}

@Override
public int getCount() {
return mList.size();
}

@Override
public Object getItem(int position) {
return mList.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder = null;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(R.layout.list_item, null);
holder = new Holder();
holder.mNameText = (TextView)convertView.findViewById(R.id.name_text);
holder.mIDText = (TextView)convertView.findViewById(R.id.id_text);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.mNameText.setText(mList.get(getCount() - position - 1).getName());
holder.mIDText.setText(mList.get(getCount() - position - 1).getID());
return convertView;
}

class Holder {
private TextView mNameText, mIDText;
}
}


PersonAdapter继承自BaseAdapter,里面的代码都应该比较熟悉。里面注意这点代码:

public void refresh(ArrayList<PersonBean> list) {

mList = list;

notifyDataSetChanged();

}

在初始化PersonAdapter的时候,需要外部导入一个mList。

public PersonAdapter(ArrayList<PersonBean> list, Context context) {

mList = list;

mContext = context;

}

在使用这种类型时,在Activity使用mAdapter.notifyDataSetChanged()时候,有时候会发现数据不能够及时的更新。这个时候,就比较需要调用refresh()这个方法了。

下面看一下主Activity:

public class ListViewRefreshActivity extends Activity {

private ListView mListView;
private ArrayList<PersonBean> mList;
private PersonAdapter mAdapter;
private Handler mHandler;
private String mName, mID;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

mListView = (ListView)findViewById(R.id.listView);
mList = new ArrayList<PersonBean>();
mAdapter = new PersonAdapter(mList, ListViewRefreshActivity.this);
mListView.setAdapter(mAdapter);

mHandler = new Handler() {

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mList.add((PersonBean) msg.obj);
Log.v("@@@@@@", "this is get message");
mAdapter.refresh(mList);
//              mAdapter.notifyDataSetChanged();
}
};

//      final Message message = new Message();
new Thread(new Runnable() {

@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
mName = "hao :" + i;
mID = "" + i;
PersonBean bean = new PersonBean();
bean.setID(mID);
bean.setName(mName);
Message message = new Message();
message.obj = bean;
Thread.sleep(3000);
mHandler.sendMessage(message);
//                      mHandler.sendMessageDelayed(message, 10000);
}}catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}


如果用这个message,注释run方法体内的message

,运行程序,在我机子上,发送第四个消息时,就会报android.util.AndroidRuntimeException:This message is already in use这个错,message已经被使用。所以,每一次发送,都要重新创建一个新的message。也可以使用一下语句:

message = mHandler.obtainMessage();

里面主要看一下handler中重写handlerMessage这个方法:

1

2

3

4

5

6

7

8

@Override

public void handleMessage(Message msg) {

super.handleMessage(msg);

mList.add((PersonBean) msg.obj);

Log.v("@@@@@@", "this is get message");

mAdapter.refresh(mList);

// mAdapter.notifyDataSetChanged();

}

当然,在这个小例子中,使用mAdapter.refresh这个方法更麻烦点,直接调用notifyDataSetChange就可以达到效果,如果你的代码里面不能达到效果,就可以使用mAdapter.refresh试一下。

notifyDataSetChanged这个方法的设计是典型观察者模式。看一下源代码:

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

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {

private final DataSetObservable mDataSetObservable = new DataSetObservable();

public boolean hasStableIds() {

return false;

}

public void registerDataSetObserver(DataSetObserver observer) {

mDataSetObservable.registerObserver(observer);

}

public void unregisterDataSetObserver(DataSetObserver observer) {

mDataSetObservable.unregisterObserver(observer);

}

/**

* Notifies the attached observers that the underlying data has been changed

* and any View reflecting the data set should refresh itself.

*/

public void notifyDataSetChanged() {

mDataSetObservable.notifyChanged();

}

/**

* Notifies the attached observers that the underlying data is no longer valid

* or available. Once invoked this adapter is no longer valid and should

* not report further data set changes.

*/

public void notifyDataSetInvalidated() {

mDataSetObservable.notifyInvalidated();

}

有一个数据被观察者:mDataSetObservable。当被观察者数据发生改变时,通知观察者。我们使用registerDataSetObserver这个方法注册观察者。都是调用notifyDataSetChanged方法。就是告诉观察者,数据有所改变。在这个方法中,又调用了DataSetObserveable的notifyChanged方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

/**

* 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) {

// since onChanged() is implemented by the app, it could do anything, including

// removing itself from {@link mObservers} - and that could cause problems if

// an iterator is used on the ArrayList {@link mObservers}.

// to avoid such problems, just march thru the list in the reverse order.

for (int i = mObservers.size() - 1; i >= 0; i--) {

mObservers.get(i).onChanged();

}

}

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐