ListView的缓存及优化原理:
1.如果有几千、几万甚至更多的项时,其中只有可见的项存在于内存中,其他的都在Recycler中,Recycler是android中专门用来处理缓存的组件;
2.ListView先通过getView()方法请求一个View,然后请求其他可见的View。convertView在getView中是空的(null);
3.当列表第一项滚出屏幕,并且一个新的项从屏幕底端上来时,ListView会再请求一个View,这时,convertView已经不是空值了,它的值是滚出屏幕的第一项,之后只需设定新的数据,然后返回convertView即可,而不必重新创建一个View;
通过这种缓存机制,大大减少了创建新View的次数,从而提升了ListView的性能。
ListView的BaseAdapter提供了如下方法:
public View getView(int position,
View convertView, ViewGroup parent)
当ListView列表里的每一项显示时,都会调用Adapter的getView方法返回一个View。
当向上滚动ListView时,getView()方法会被反复调用。getView()的第二个参数convertView是被缓存起来的List条目中的View对象。当ListView滑动的时候,getView可能会直接返回旧的convertView。这里使用了convertView和ViewHolder,可以充分利用缓存,避免反复创建View对象和TextView对象。
如果ListView的条目只有几个,这种技巧并不能带来多少性能的提升。但是如果条目有几百甚至几千个,使用这种技巧只会创建几个convertView和ViewHolder(取决于当前界面能够显示的条目数),性能的差别就非常非常大了。
这是自己敲的一个例子:
import java.util.ArrayList;
import com.beyond.bean.Blogger;
import com.example.comment.R;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class BloggerListAdapter extends BaseAdapter {
private ArrayList bloggerList;
private Context context;// 这里上下文指整个应用
public BloggerListAdapter(ArrayList
bloggerList,
Context
applicationContext) {
this.bloggerList =
bloggerList;
this.context =
applicationContext;
}
//得到真实的数据源项数,
@Override
public int getCount() {
// TODO Auto-generated method
stub
return
bloggerList.size();
}
//返回某一项数据
@Override
public Object getItem(int position) {
// TODO Auto-generated method
stub
return
bloggerList.get(position);
}
//返回某一项的行ID
verride
public long getItemId(int position) {
// TODO Auto-generated method
stub
return position;
}
//对于ListView中的数据,显示每一行数据都要调用一次该方法,convertView和ViewHolder一同完成缓存机制
//以优化性能
@Override
public View getView(int position, View
convertView, ViewGroup parent) {
// TODO Auto-generated method
stub
View view = convertView;
ViewHolder vh;
if (view == null) {
//创建新的view
LayoutInflater
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view =
inflater.inflate(R.layout.bloggerlist_item, null);
vh = new
ViewHolder();
//每项的视图布局是一样的
vh.blogger =
(TextView) convertView.findViewById(R.id.blogger);
vh.date =
(TextView) convertView.findViewById(R.id.date);
vh.time =
(TextView) convertView.findViewById(R.id.time);
vh.blogCount
= (TextView) convertView.findViewById(R.id.blogCount);
vh.tuxiang =
(ImageView) convertView.findViewById(R.id.tuxiang);
view.setTag(vh);
} else
//使用缓存的view
vh =
(ViewHolder) view.getTag();
//每项的数据是不一样的
vh.blogger.setText(bloggerList.get(position).getName());
vh.date.setText(bloggerList.get(position).getDate());
vh.time.setText(bloggerList.get(position).getTime());
vh.blogCount.setText(bloggerList.get(position).getBlogCount()
+ "篇博文");
vh.tuxiang.setImageBitmap(bloggerList.get(position).getTuxiang());
return convertView;
}
// 用来实现缓存机制
class ViewHolder {
TextView blogger, date, time,
blogCount;
ImageView tuxiang;
}
@Override
public void notifyDataSetChanged() {
// TODO Auto-generated method
stub
super.notifyDataSetChanged();
}
}