众所周知Listview和Gridview的刷新界面的方式是调用adapter.notifyDataSetChanged()进行界面刷新。
但是此方法有其弊端,他是将界面中的数据全部刷新一遍,不论数据有没有变化。如果listview加载了很多的数据(如:100条)
在进行刷新时就会造成很大的系统开销如何像qq空间个人动态那样点赞只刷新一条呢:
主要原理:
对listview的某一个item进行刷新
1.要获取要刷新的item当前索引position和数据
2.对获取的数据进行重置
3.将重置的数据放到adapter中的数据集的原来的位置(根据position刷新原数据集的某一条数据)
4.在listview中获取需要刷新的子item的view
5.从更新过的数据集中获取新数据,更新viwe中的数据(handler中操作,实现界面的刷新)
功能如下,代码中有详细注释:
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()); } @Override public int getCount() { // TODO Auto-generated method stub return mDataList.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return mDataList.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub 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; } }
原文地址:http://blog.csdn.net/u013626215/article/details/45579209