在使用ListView时,需要刷新数据的时候,我们通常的做法是调用mAdapter.notifyDataSetChanged()刷新界面,毫无疑问这很简单,现在咱们测试一下其效率,并对其进行优化。
1.罗列代码:
MainActivity 的内容:
package com.example.androidtest;
import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener {
ListView mListView;
TextViewAdapter mAdapter;
TextView notifyView;
TextView refreshItemView;
@Override
public void onClick(View v) {
switch (v.getId()) {
case 0x11: {
//使用一般方法刷新UI
String targetString = "2";
int targetIndex = -1;
// 1.查找text内容为"2"的下标;
for (int j = 0; j < mListView.getCount(); j++) {
String itemString = (String) mListView.getItemAtPosition(j);
if (targetString.equals(itemString)) {
targetIndex = j;
break;
}
}
if (targetIndex >= 0) {
mAdapter.setGreenItem(targetIndex);
***mAdapter.notifyDataSetChanged();***
}
}
break;
case 0x22: {
//使用高效的方法刷新UI(当然如果postion不在页面上,不需要刷新)
// 1.我们想要修改text内容为"2"的Item的位置
String targetString = "2";
int targetIndex = -1;
for (int j = 0; j < mListView.getCount(); j++) {
String itemString = (String) mListView.getItemAtPosition(j);
if (targetString.equals(itemString)) {
targetIndex = j;
break;
}
}
if (targetIndex >= 0) {
mAdapter.setGreenItem(targetIndex);
int startShownIndex = mListView.getFirstVisiblePosition();
int endShownIndex = mListView.getLastVisiblePosition();
***if (targetIndex >= startShownIndex
&& targetIndex <= endShownIndex) {
View view = mListView.getChildAt(targetIndex
- startShownIndex);
mListView.getAdapter()
.getView(targetIndex, view, mListView);
}***
}
}
break;
default:
break;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout outLayout = new LinearLayout(this);
outLayout.setOrientation(LinearLayout.VERTICAL);
notifyView = new TextView(this);
notifyView.setId(0x11);
notifyView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, 100));
notifyView.setText("调用notifyDataSetChange刷新数据");
notifyView.setGravity(Gravity.CENTER);
refreshItemView = new TextView(this);
refreshItemView.setId(0x22);
refreshItemView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, 100));
refreshItemView.setText("调用refresh Item刷新数据");
refreshItemView.setGravity(Gravity.CENTER);
mListView = new ListView(this);
outLayout.addView(notifyView);
outLayout.addView(refreshItemView);
outLayout.addView(mListView);
setContentView(outLayout);
mAdapter = new TextViewAdapter(this);
mListView.setAdapter(mAdapter);
notifyView.setOnClickListener(this);
refreshItemView.setOnClickListener(this);
}
}
2.TextViewAdapter 的内容:
package com.example.androidtest;
import android.content.Context;
import android.graphics.Color;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class TextViewAdapter extends BaseAdapter {
Context mContext;
int mGreenPostion = -1;
public TextViewAdapter(Context context) {
mContext = context;
}
/**
* 为了简单起见,这里仅仅允许设置一个Item的背景色为绿色
*
* @param position
*/
public void setGreenItem(int position) {
mGreenPostion = position;
// 注意为了提高UI效率这个直接调用notifyDataSetChange();
}
@Override
public int getCount() {
return 10;
}
@Override
public String getItem(int position) {
return position + "";
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = new ViewHolder();
TextView outerLayout = new TextView(mContext);
outerLayout.setGravity(Gravity.CENTER);
outerLayout.setTextSize(50);
outerLayout.setTextColor(Color.BLUE);
AbsListView.LayoutParams outerParams = new AbsListView.LayoutParams(
new LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, 300));
outerLayout.setLayoutParams(outerParams);
viewHolder.itemLayout = outerLayout;
convertView = outerLayout;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.itemLayout.setText(getItem(position));
if (position == mGreenPostion) {
viewHolder.itemLayout.setBackgroundColor(Color.GREEN);
} else {
viewHolder.itemLayout.setBackgroundColor(Color.WHITE);
}
System.err.println("-------position--" + position);
return convertView;
}
class ViewHolder {
TextView itemLayout;
}
}
结果比较:
1.调用常规的notifyDataSetChange的时候,getView的调用情况如下:
2.调用精致的refreshItem(自鸣得意的一个名字),结果如下:
仅仅调用了一次,amazing!!!
结论:
使用adapter.notifyDataSetChange方法简单,但效果不佳;使用精致的方法:
if (targetIndex >= startShownIndex
&& targetIndex <= endShownIndex) {
View view = mListView.getChildAt(targetIndex
- startShownIndex);
mListView.getAdapter()
.getView(targetIndex, view, mListView);
}
刷新UI会大大提高。
参考地址:http://stackoverflow.com/questions/2123083/android-listview-refresh-single-row