Android关于ListView的优化

当使用自定义Adapter来创建ListView时,注意以下几点,可以起到优化的作用:

  1. 在XML文件布局ListView时,android:layout_height不要定义为wrap_content,并且ListView的所有父节点布局的android:layout_height都不要定义为wrap_content。
    正常情况下,一屏幕显示多少item,那么Adapter中的getView()函数会被调用几次。如果android:layout_height定义为wrap_content,那么getView()将被成倍调用。所以,建议使用fill_parent或者固定高度尺寸。

  2. 在getView()函数中,通过convertView != null的判断来复用convertView。

  3. 定义一个内部类ViewHolder,其中包含了item布局中的各个控件。
    在初始化convertView时,也new一个ViewHolder,来保存convertView中的各个子控件。当复用convertView时,直接对相应的ViewHolder进行改动即可。避免convertView的findViewById()的耗时操作。

activity_demo_list.xml

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent" 
android:layout_height="fill_parent"
android:orientation="vertical">

<ListView
    android:id="@+id/list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>

demo_list_item.xml

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical">
<TextView 
    android:id="@+id/text"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:textSize="20sp"
    android:textColor="@android:color/background_dark"/>

public class DemoSimpleAdapter extends BaseAdapter {

private List<String> mData = new ArrayList<String>();
private Context mContext;
private LayoutInflater mFlater;

private static class ViewHolder {
    public View bgView;
    public TextView text;
}

public DemoSimpleAdapter(Context context, List<String> data){
    this.mContext = context;
    this.mData = data;
    this.mFlater = LayoutInflater.from(mContext);
}

public void resetData(List<String> data){
    this.mData = data;
    this.notifyDataSetChanged();
}

@Override
public int getCount() {
    // TODO Auto-generated method stub
    return mData.size();
}

@Override
public Object getItem(int position) {
    // TODO Auto-generated method stub
    return mData.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
    ViewHolder viewHolder = null;
    if ( convertView == null ) {
        convertView = mFlater.inflate(R.layout.demo_list_item,null);
        viewHolder = new ViewHolder();
        viewHolder.bgView = convertView;
        viewHolder.text = (TextView) convertView.findViewById(R.id.text);
        convertView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }
    if( position%2 == 0 ) {
        viewHolder.bgView.setBackgroundColor(Color.parseColor("#ffffff"));
    } else {
        viewHolder.bgView.setBackgroundColor(Color.parseColor("#f8fbd9"));
    }
    viewHolder.text.setText(mData.get(position));
    return convertView;
}

}

4.分页加载:每次只加载固定数量的items,当滑动到ListView底部时,FooterView显示“正在加载”,加载其他数据。

<1>. 定义FooterView的布局:paging_load_list_footer.xml

<LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”

android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="10dip"
android:paddingBottom="10dip"
android:background="@android:color/background_light"
android:orientation="horizontal"
android:gravity="center" >
<ProgressBar 
    android:id="@+id/pb_refresh"
    android:layout_width="20dip"
    android:layout_height="20dip"
    style="@android:attr/progressBarStyleSmall" />
<TextView 
    android:id="@+id/tv_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dip"
    android:textSize="14sp"
    android:textColor="@android:color/background_dark"
    android:text="正在加载中..." />

<2>. 定义上拉刷新监听器OnFootLoadingListener。
public interface OnFootLoadingListener{

/** 
 * 这里是执行后台获取数据的过程 
 */  
void onFootLoading();  

}

<3>. 定义实现分页加载功能的PagingLoadListView
public class PagingLoadListView extends ListView {

public int mDataTotalSize = 0;          //数据集的全部条数
private int mVisibleLastIndex;          //最后的可视项索引
private int mTotalItemCount;            //ListView已经加载的数据项(如果有HeaderView,要-1。如果有FooterView,也要-1)。
private View mFooterView;
private boolean mIsFootLoading = false;     //是否正在加载底部数据
private OnFootLoadingListener mFootLoadingListener = null;

public PagingLoadListView(Context context) {
    super(context);
    init();
}

 public PagingLoadListView(Context context, AttributeSet attrs) {
     super(context, attrs);
     init();
}

public PagingLoadListView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
}

public void setOnFootLoadingListener(OnFootLoadingListener listener) {
    mFootLoadingListener = listener;
}

public void onFootLoadingComplete(){
    mIsFootLoading = false;
}

private void init() {
    // 动态加载底部View
    LayoutInflater flater = LayoutInflater.from(getContext());
    mFooterView = flater.inflate(R.layout.paging_load_list_footer, null);
    this.addFooterView(mFooterView);
    // 设置透明背景
    this.setCacheColorHint(0x00000000);

    this.setOnScrollListener(new OnScrollListener(){

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {
            mVisibleLastIndex = getLastVisiblePosition();
            mTotalItemCount = totalItemCount - 1; //要减去FooterView

            if( mVisibleLastIndex == mTotalItemCount && mVisibleLastIndex != -1 && //滑动到底部
                    mDataTotalSize == mTotalItemCount ) { //全部数据都加载完了
                ProgressBar pb = (ProgressBar) mFooterView.findViewById(R.id.pb_refresh);
                pb.setVisibility(View.GONE);
                TextView tv = (TextView) mFooterView.findViewById(R.id.tv_title);
                if ( mDataTotalSize != 0 ) {
                    tv.setText("数据加载完毕");
                } else {
                    tv.setText("没有数据");
                }
            }  

        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {  
            if( mIsFootLoading == false && scrollState == SCROLL_STATE_IDLE &&
                    mFootLoadingListener != null  && mVisibleLastIndex > 0  && 
                    mVisibleLastIndex == mTotalItemCount  && mVisibleLastIndex != mDataTotalSize ) {
                //执行底部加载
                mIsFootLoading = true;
                mFootLoadingListener.onFootLoading();
            }  
        }
    });
}

}

<4>. 使用PagingLoadListView,设置OnFootLoadingListener,在回调函数中先重新加载数据,然后调用onFootLoadingComplete()。

你可能感兴趣的:(优化ListView)