衆所周知listview和gridview的重新整理界面的方式是調用adapter.notifydatasetchanged()進行界面重新整理。
但是此方法有其弊端,他是将界面中的資料全部重新整理一遍,不論資料有沒有變化。如果listview加載了很多的資料(如:100條)
在進行重新整理時就會造成很大的系統開銷如何像qq空間個人動态那樣點贊隻重新整理一條呢:
主要原理:
對listview的某一個item進行重新整理
1.要擷取要重新整理的item目前索引position和資料
2.對擷取的資料進行重置
3.将重置的資料放到adapter中的資料集的原來的位置(根據position重新整理原資料集的某一條資料)
4.在listview中擷取需要重新整理的子item的view
5.從更新過的資料集中擷取新資料,更新viwe中的資料(handler中操作,實作界面的重新整理)
功能如下,代碼中有詳細注釋:
[java] view
plaincopyprint?
public class mainactivity extends activity
{
private arraylist<mylistitem> list = null;
private listview lv;
private mylistadapter adapter;
@override
protected void oncreate(bundle savedinstancestate)
{
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
intitdata();
lv = (listview) findviewbyid(r.id.listview1);
adapter = new mylistadapter(list, getapplicationcontext());
adapter.setlistview(lv);
lv.setadapter(adapter);
lv.setonitemclicklistener(new onitemclicklistener()
{
@override
public void onitemclick(adapterview<?> parent, view view, int position, long id)
{
// 擷取listview中點選item的資料
mylistitem item = (mylistitem) parent.getitematposition(position);
log.i("eee", item.getdata() + " == " + item.getposition());
// 更新資料
item.setdata("update item " + position);
// 更新界面
adapter.updateitemdata(item);
}
});
}
/**
* 初始化資料
*/
private void intitdata()
list = new arraylist<mylistitem>();
for (int i = 0; i < 20; i++)
mylistitem item = new mylistitem();
item.setdata("item " + i);
item.setposition(i);
list.add(item);
}
* 自定義item資料類型
class mylistitem
/**
* 資料id
*/
private int dataid;
* 資料
private string data;
public int getposition()
return dataid;
public void setposition(int position)
this.dataid = position;
public string getdata()
return data;
public void setdata(string data)
this.data = data;
}
activity進行調用,功能操作主要封裝在adapter中如下:
public class mylistadapter extends baseadapter
* listview中的資料集
private arraylist<mylistitem> mdatalist;
private context mcontext;
private listview mlistview;
public mylistadapter(arraylist<mylistitem> list, context cont)
this.mdatalist = list;
this.mcontext = cont;
* 設定listview對象
*
* @param lisv
public void setlistview(listview lisv)
this.mlistview = lisv;
* update listview 單條資料
* @param item 新資料對象
public void updateitemdata(mylistitem item)
message msg = message.obtain();
int ids = -1;
// 進行資料對比擷取對應資料在list中的位置
for (int i = 0; i < mdatalist.size(); i++)
if (mdatalist.get(i).getposition() == item.getposition())
ids = i;
msg.arg1 = ids;
// 更新mdatalist對應位置的資料
mdatalist.set(ids, item);
// handle重新整理界面
han.sendmessage(msg);
@suppresslint("handlerleak")
private handler han = new handler()
{
public void handlemessage(android.os.message msg)
{
updateitem(msg.arg1);
};
};
* 重新整理指定item
* @param index item在listview中的位置
private void updateitem(int index)
if (mlistview == null)
return;
// 擷取目前可以看到的item位置
int visibleposition = mlistview.getfirstvisibleposition();
// 如添加headerview後 firstview就是hearderview
// 所有索引+1 取第一個view
// view view = listview.getchildat(index - visibleposition + 1);
// 擷取點選的view
view view = mlistview.getchildat(index - visibleposition);
textview txt = (textview) view.findviewbyid(r.id.textview1);
// 擷取mdatalist.set(ids, item);更新的資料
mylistitem data = (mylistitem) getitem(index);
// 重新設定界面顯示資料
txt.settext(data.getdata());
public int getcount()
// todo auto-generated method stub
return mdatalist.size();
public object getitem(int position)
return mdatalist.get(position);
public long getitemid(int position)
return position;
public view getview(int position, view convertview, viewgroup parent)
if (convertview == null)
convertview = layoutinflater.from(mcontext).inflate(r.layout.list_item, null);
textview txt = (textview) convertview.findviewbyid(r.id.textview1);
txt.settext(mdatalist.get(position).getdata());
return convertview;
由于listview與gridview功能相似,隻是顯示方式不同,原理一樣,需要的同學可以自己修改一下試試