安卓开发中ListView控件是一个使用频率相当的高级控件,通常用于展示一系列相似度极高的数据,当数据量极大或布局相当复杂时,ListView的性能优化就显得非常重要。所以在开发中不但功能上要满足,而且在性能上也不能马虎。
使用ListView是一个标准的适配器设计模式,ListView把数据、XML布局和Adapter有极地结合在一起完成一系列的展示功能。在ListView的数据展示中,每次滑动ListView都会触发getView()方法的调用,并且XML定义的布局是在也是在适配器的getView()方法中使用布局加载器LayoutInflater加载,LayoutInflater加载布局是件相当耗资源的事儿,又加之findViewById()方法是一个耗时的操作,由此看出频繁的inflater()和findViewById()操作会给应用带来相当严重的性能问题,所以ListView的性能优化是刻不容缓的,好在Google工程师已经为我们提供了相应的解决方案,ListView的缓存功能。
看例子之前先看看效果图:
下面就通过一个简单的Demo来诠释上面的描述。
package com.hitech.convertholderdemo; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.CheckBox; import android.widget.ListView; import android.widget.TextView; public class MainActivity extends Activity { public static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listView = (ListView) findViewById(R.id.lv_activity_main); listView.setAdapter(new ListViewDataAdapter()); } private class ListViewDataAdapter extends BaseAdapter { private List<String> list = new ArrayList<String>(); public ListViewDataAdapter() { for (int i = 0; i < 100; i++) { list.add(i + ""); } } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = null; ViewHolder holder = null; if (convertView != null) { // 如果convertView中有缓存 view = convertView; // 直接使用缓存并从中取出缓存的ViewHolder对象 holder = (ViewHolder) view.getTag(); Log.e(TAG, "使用缓存的convertView" + position); } else { Log.e(TAG, "没有缓存的convertView" + position); // 如果没有缓存,就从XML文件加载布局 view = getLayoutInflater().inflate( R.layout.dialog_popup_main_activity, null); // 将加载布局中的控件缓存到ViewHolder中 holder = new ViewHolder(); holder.textview_username = (TextView) view .findViewById(R.id.textview_username); holder.textview_nickname = (TextView) view .findViewById(R.id.textview_nickname); holder.checkbox_selected = (CheckBox) view .findViewById(R.id.checkbox_selected); // 把holder对象做为数据存到view view.setTag(holder); } // 对布局中的控件进行设置 由于 holder.textview_nickname.setText(list.get(position)); holder.textview_username.setText(list.get(position)); holder.checkbox_selected.setText(list.get(position)); return view; } } public static class ViewHolder { // 对布局文件中的控件按面向对象思想封装 TextView textview_username = null; TextView textview_nickname = null; CheckBox checkbox_selected = null; } }