android ListView控件

1)ListView滚动速度优化

ListView滚动速度优化主要可以应用以下几点方法来实现:

1、使用Adapter提供的convertView

convertView是Adapter提供的视图缓存机制,当第一次显示数据的时候,adapter会创建n个(n等于页面可见的item的数目)convertView,当下次需要显示新的item的时候,adapter会循环利用这些已经创建的convertView,减少再次创建convertView所带来的开销,从而达到性能的提升。

 

2、使用自定义的视图缓存类

就是自定义一个视图缓存类,在这个类中保存我们在item中使用到的视图的引用,通过convertView的setTag方法和getTag方法来存储这个视图缓存类引用和重新获取这个视图缓存类引用,其目的也是为了减少重复创建视图时的开销。

 

3、减少不必要的视图更新

ListView在滚动时会请求重新获取item,来显示不同内容的item,而如果在获取item时比较耗时就会造成在滚动时出现卡顿的现象。那我们可以通过监听ListView的滚动事件来使ListView处于不同的滚动状态时做不同的事情,比如在ListView处于滚动过程中加载少量的显示数据,当ListView处于空闲的状态时再加载所有的数据,这样就可以减少ListView在滚动过程中的开销,从而提供ListView的滚动速度。

以上只是我使用过的优化ListView的滚动速度的方法,如果你有什么更好的方法,欢迎一起讨论。

下面是一个完整的小例子,仅供参考,欢迎指正:

main.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/ui_main_listview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_centerInParent="true"
        android:background="@color/background_main"
        android:cacheColorHint="#00000000"
        android:divider="@color/list_divider"
        android:dividerHeight="1px"
        android:fastScrollAlwaysVisible="true"
        android:fastScrollEnabled="true"
        android:listSelector="@drawable/list_selector_bg"
        android:paddingLeft="5dip"
        android:paddingRight="5dip" />

</LinearLayout>


ListView中item的布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <RelativeLayout
        android:id="@+id/ui_main_left"
        android:layout_width="48dip"
        android:layout_height="55dip"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" >

        <ImageView
            android:id="@+id/ui_main_icon"
            android:layout_width="48dip"
            android:layout_height="48dip"
            android:layout_centerInParent="true"
            android:src="@drawable/image_icon_folder" />
    </RelativeLayout>

    <TextView
        android:id="@+id/ui_main_txt_name"
        style="@style/larger_title_text_style"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dip"
        android:layout_marginRight="10dip"
        android:layout_marginTop="10dip"
        android:layout_toRightOf="@+id/ui_main_left"
        android:singleLine="true" />

    <TextView
        android:id="@+id/ui_main_txt_size"
        style="@style/detail_text_style"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/ui_main_txt_name"
        android:layout_marginLeft="10dip"
        android:layout_marginTop="6dip"
        android:layout_toRightOf="@+id/ui_main_left" />

    <TextView
        android:id="@+id/ui_main_txt_time"
        style="@style/detail_text_style"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/ui_main_txt_name"
        android:layout_marginRight="10dip"
        android:layout_marginTop="6dip" />

</RelativeLayout>


显示界面

package com.ygc;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.widget.AbsListView;
import android.widget.ListView;

public class ListOptimizationActivity extends Activity {

	// ListView 和 adapter
	private ListView mListView = null;
	private MainAdapter mAdapter = null;

	// context
	private Context mContext;
	/**
	 * ListView滚动监听,用于当ListView处于滚动的不同状态时做相应的操作
	 * */

	AbsListView.OnScrollListener mScrollListener = new AbsListView.OnScrollListener() {

		public void onScroll(AbsListView view, int firstVisibleItem,
				int visibleItemCount, int totalItemCount) {
			mAdapter.stopRefresh(false);

		}

		public void onScrollStateChanged(AbsListView view, int scrollState) {
			/**
			 * 当ListView停止滚动,并且手指离开屏幕,整个ListView处于空闲状态时
			 * */
			if (scrollState == SCROLL_STATE_IDLE) {
				mAdapter.refresh();
			}

			/**
			 * 当ListView从空闲状态变为滚动状态时
			 * */
			if (scrollState == SCROLL_STATE_TOUCH_SCROLL) {
				mAdapter.stopRefresh(true);
			}

		}

	};

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		mContext = getApplicationContext();
		initUI();
	}

	/**
	 * 初始化控件
	 * */
	private void initUI() {
		mListView = (ListView) findViewById(R.id.ui_main_listview);
		mAdapter = new MainAdapter(mContext);
		mListView.setAdapter(mAdapter);
		mListView.setOnScrollListener(mScrollListener);
		mAdapter.refresh();
	}
}


ListView用到的Adapter

package com.ygc;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MainAdapter extends BaseAdapter {
	// 监听会初始化几次getView方法中的convertView变量
	int callCount = 0;
	private LayoutInflater factory;

	private ViewHolder viewHolder = null;

	// 加载数据标识位,为false时,只显示item名字,为true时,显示所有数据
	private boolean refresh = true;
	/**
	 * 下面是ListView显示时用到的数据, 这里为了方便,并没有动态地获取数据, 而是使用静态数据的方法
	 * */

	// 用到的图片的资源ID
	private int[] jpgResourceIds = { R.drawable.item0, R.drawable.item1,
			R.drawable.item2, R.drawable.item3, R.drawable.item4,
			R.drawable.item5, R.drawable.item6, R.drawable.item7,
			R.drawable.item8, R.drawable.item9, R.drawable.item10 };

	// item的名字
	private String[] itemNames = { "item0", "item1", "item2", "item3", "item4",
			"item5", "item6", "item7", "item8", "item9", "item10" };

	// item资源的大小
	private String[] itemResourceSizes = { "1.0MB", "968KB", "1.45MB", "55KB",
			"100KB", "86KB", "3.5MB", "9.0MB", "55KB", "18KB", "40KB" };

	// item资源的修改日期
	private String[] itemResourceModifiedTimes = { "2012-03-01 19:20",
			"2012-03-01 19:20", "2012-03-01 19:20", "2008-02-09 13:20",
			"2003-11-01 19:20", "2000-12-01 23:20", "2010-06-11 15:20",
			"2002-04-21 12:00", "2012-01-01 13:29", "2012-02-01 09:30",
			"2012-03-05 13:00" };

	public MainAdapter(Context context) {
		factory = (LayoutInflater) context
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

	}

	/**
	 * 返回110个item,循环利用上述资源
	 * */
	public int getCount() {
		return itemNames.length * 1000;
	}

	public Object getItem(int position) {
		return null;
	}

	public long getItemId(int position) {
		return position;
	}

	public View getView(int position, View convertView, ViewGroup parent) {

		long startTime = System.currentTimeMillis();

		// 初始化视图控件
		if (null == convertView) {
			Log.e("MainAdapter", "the convertView count is " + callCount++);
			convertView = factory.inflate(R.layout.item_layout, null);
			viewHolder = new ViewHolder();
			viewHolder.imgIcon = (ImageView) convertView
					.findViewById(R.id.ui_main_icon);
			viewHolder.txtName = (TextView) convertView
					.findViewById(R.id.ui_main_txt_name);
			viewHolder.txtSize = (TextView) convertView
					.findViewById(R.id.ui_main_txt_size);
			viewHolder.txtTime = (TextView) convertView
					.findViewById(R.id.ui_main_txt_time);
			convertView.setTag(viewHolder);
		} else {
			viewHolder = (ViewHolder) convertView.getTag();
		}
		if (refresh) {
			viewHolder.imgIcon.setVisibility(View.VISIBLE);
			viewHolder.txtSize.setVisibility(View.VISIBLE);
			viewHolder.txtTime.setVisibility(View.VISIBLE);
			viewHolder.imgIcon.setImageResource(jpgResourceIds[position % 11]);
			viewHolder.txtName.setText(itemNames[position % 11]);
			viewHolder.txtSize.setText(itemResourceSizes[position % 11]);
			viewHolder.txtTime
					.setText(itemResourceModifiedTimes[position % 11]);
		} else {
			viewHolder.imgIcon.setVisibility(View.INVISIBLE);
			viewHolder.txtName.setText(itemNames[position % 11]);
			viewHolder.txtSize.setVisibility(View.INVISIBLE);
			viewHolder.txtTime.setVisibility(View.INVISIBLE);
		}
		long endTime = System.currentTimeMillis();
		long elapse = endTime - startTime;
		Log.e("MainAdapter ", "the elapse time in the getView method is "
				+ elapse);
		return convertView;
	}

	/**
	 * 控件缓存 用于缓存item中的控件,加快listview的滚动速度, 只需进行一次初始化,然后可以重复使用。
	 * */
	class ViewHolder {
		public ImageView imgIcon = null;
		public TextView txtName = null;
		public TextView txtSize = null;
		public TextView txtTime = null;
	}

	/**
	 * 调用此方法会强制adapter重新调用getView方法,并设置标志位refresh为true
	 * */
	public void refresh() {
		refresh = true;
		this.notifyDataSetChanged();
	}

	/**
	 * 设置标志位refresh为false
	 * 
	 * @param boolean flag 是否通知adapter更新视图内容,true更新,否则不更新
	 * */
	public void stopRefresh(boolean flag) {
		refresh = false;
		if (flag) {
			this.notifyDataSetChanged();
		}
	}

}


 

2)点击ListView中的Item时Item的背景颜色控制

在xml文件中的ListView控件中加入如下属性:

android:listSelector="@drawable/timer_list_selector"


在drawable中定义timer_list_selector的属性值
timer_list_selector.xml中定义如下:

<?xml version="1.0" encoding="utf-8"?>

    <selector xmlns:android="http://schemas.android.com/apk/res/android" >

        <item
            android:drawable="@android:color/transparent"
            android:state_selected="true"/>
    </selector>

 

在values文件夹下的colors.xml中定义transparent如下:

<color name="transparent">#50000000</color>

上述设置产生的效果是点击Item是Item背景无颜色变化。

 

3)设置ListView中Item之间的分割线

android:divider="@drawable/list_driver"

其中  @drawable/list_driver 是一个图片资源,如果不想显示分割线则只要设置为android:divider="@drawable/@null" 就可以了。或者在xml文件中ListView控件中加入如下属性:

android:divider="#00000000"

或者在javaCode中如下定义:

listView.setDividerHeight(0);

 

4)解决ListView滚动时背景颜色变黑

在ListView下加入如下属性

android:cacheColorHint="#00000000"

 

5)解决ListView滚动时上下边界有阴影

在ListView下加入如下属性

android:fadingEdge="none"



 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值