(1).重写适配器的getView方法时,getView方法有三个参数
public View getView(int position,View convertView,ViewGroup parent)
<span style="white-space:pre"> </span>有了这个参数,我们不必每调用一次getView,就重新加载一次布局,
其中第二个参数convertView用于将之前加载好的布局进行缓存。getView()方法列表子项滚动到屏幕内就会调用一次,用户频繁滑动就会频繁的调用getView,所以里面最好不要有很耗时的操作,比如每调用一次getView方法就重新加载一次布局,当用户频繁的滑动列表时,频繁的调用getView(),然后频繁的重新加载布局.....
我们可以用第二个参数,判断一下是否有缓存,有的话直接重用,没有就用inflate方法动态加载布局。
public View getView(int position,View convertView,ViewGroup parent){
View mView;
if(convertView==null){//没有缓存
mView=LayoutInflater.from(this).inflate(R.layout.list_item,null);
}
else{//有缓存,重用,不用inflate加载了
mView=convertView;
}
TextView textView=(TextView) mView.findViewById(R.id.text_view);
textView.setText("...");
return mView;
}
(2).在(1)的代码中,如果用户频繁滑动列表,getView()方法频繁调用,那么上述代码中TextView textView=(TextView) mView.findViewById(R.id.text_view)会在随着getView()方法的调用,一次一次的获取控件的实例。
public class xxAdapter extends ArrayAdapter<xx>{
.......
public View getView(int position,View convertView,ViewGroup parent){
View mView;
ViewHolder viewHolder;
if(convertView==null){
mView=LayoutInflater.from(this).inflate(R.layout.list_item,null);
viewHolder.textView=(TextView)findViewById(R.id.text_view);
mView.setTag(viewHolder)://将ViewHolder存储到View中,setTag方法给View添加额外数据
}
else{
mView=convertView;
viewHolder=(ViewHolder) mView.getTag();//获取原先存储的ViewHolder
}
viewHolder.textView.setText("...");
return mView;
}
static class ViewHolder{//设置为静态,第一次加载会花费些时间,后面加载就方便了,而且只有一个ViewHolder,节省内存。
TextView textView;
}
}
扩展:关于上述代码的setTag()方法,一个例子(给Button添加额外的数据以判断是点击的是哪个Button)
public class MyActivity extends Activity implements View.OnClickListener{
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
Button button1=(Button)findViewById(...);
button1.setTag(1);
Button button2=(Button)findViewById(...);
button2.setTag(2);
button1.setOnClickListener(this):
button2.setOnClickListener(this):
}
public void onClick(View v){
switch(v.getTag()){
case 1:
Toast.makeText(MyActivity.this,"1",Toast.LENGTH.SHORT).show();
break;
case 2:
Toast.makeText(MyActivity.this,"2",Toast.LENGTH.SHORT).show();
break;
}
}
}
(3)由于用户滑动列表就会调用getView方法,所以getView方法不能做耗时操作,比如我们想在ListView里面显示我们从网站上获取的图片,加载图片的方法不能放在getView方法中,可以进行异步处理。
(4)对于第三点,在加载图片的情况下,当用户来回上下滑动,就会一瞬间产生很多异步任务,也就是很多UI的更新操作,UI的更新发生在主线程中,有可能造成界面卡顿,而且这些大量的异步任务会造成线程池的拥堵。
我们可以等用户滑动列表停下来时再进行加载图片。
给ListView设置setOnScrollListener, 利用OnScrollListener的onScrollStateChanged方法判断列表的状态,是滑动还是停止,如果是滑动就不加载图片,如果列表停止就加载图片。
listView.setOnScrollListener(new AbsListView.OnScrollListener){
public void onScrollStateChanged(AbsListView view,int scrollState){
if(scrollState==OnScrollListener.SCROLL_STATE_IDLE) {
isStop=true;
xxAdapter.notifyDataSetChanged();
else{
isStop=false;
}
}
}
然后在xxAdapter的getView方法中判断一下是否停止,停止时再加载图片。
(5)开启硬件加速,设置android:hardwareAccelerated="true"为活动开启硬件加速