(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"爲活動開啓硬件加速