Android性能優化之ListView緩存機制
要想優化ListView首先要了解它的工作原理,列表的顯示須要三個元素:ListView、Adapter、顯示的數據。
這裏的Adapter就是用到了適配器模式,無論傳入的是什麽View在ListView中都能顯示出來。
1、假設你有幾千幾萬甚至很多其它的選項(item)時。當中僅僅有可見的項目(滿屏顯示的Item數目)存在內存(說的優化就是說在內存中的優化!)中,其它的在Recycler中
2、ListView先請求一個type1視圖(getView)然後請求其它可見的項目。convertView在getView中是空(null)的。第一次都是為空的。僅僅要顯示過了convertView都不為空,會保存在Recycler中
3、當item1滾出屏幕。而且一個新的項目從屏幕低端上來時。ListView再請求一個type1視圖。
convertView此時不是空值了,它的值是item1。你僅僅需設定新的數據然後返回convertView,不必又一次創建一個視圖,省去了inflate和findViewById的時間,性能就得到了優化。
了解了它的工作原理後,我們就能夠反復利用convertView,僅僅要不為空就直接使用。改變它的內容即可了。
使用ListView的時候都會搭配一個Adapter,為了使得性能更優。ListView會緩存行item(某行相應的View)。ListView通過Adapter的getView函數獲得每行的item。
package com.dzt.listviewdemo; import java.util.ArrayList; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; public class MainActivity extends Activity { private ListAdapter adapter; private ListView lv = null; private ArrayList<String> list = new ArrayList<String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lv = (ListView) findViewById(R.id.lv_list); adapter = new ListAdapter(); for (int i = 0; i < 100; i++) { list.add("item " + i); } lv.setAdapter(adapter); } private class ListAdapter extends BaseAdapter { private LayoutInflater mInflater; ListAdapter() { mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { // TODO Auto-generated method stub return list.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return list.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 System.out.println("getView " + position + " " + convertView); viewHolder holder = null; if (convertView == null) { convertView = mInflater.inflate(R.layout.item, null); holder = new viewHolder(); holder.text = (TextView) convertView.findViewById(R.id.tv_text); holder.image = (ImageView) convertView .findViewById(R.id.iv_img); convertView.setTag(holder); } else { holder = (viewHolder) convertView.getTag(); } holder.text.setText(list.get(position)); if (position % 2 == 0) { holder.image.setImageResource(R.drawable.ic_launcher); } else { holder.image.setImageResource(R.drawable.icon); } return convertView; } } /** * 使用一個類來保存Item中的元素 * * @author Administrator * */ public static class viewHolder { public TextView text; public ImageView image; } }
第一次打印的結果convertView都是為null
滑動ListView後的打印
從上面的打印消息能夠看出,Recycler中會保存七個convertView對象用來顯示Item。無論你有上千個Item,也僅僅會創建顯示滿屏的convertView。這就大大節省了內存,對viewHolder的Tag的使用也大大節省了性能開銷
相關代碼下載:http://download.csdn.net/detail/deng0zhaotai/7842885
Android性能優化之ListView緩存機制