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"