android ListView优化是通过复用历史缓存实现的。listview对应的数据适配器一般用自定义的BaseAdapter子类,复用历史缓存提高性能。示例代码如下:
1、listView数据适配器
/**
* 待处理请假信息的数据适配器类
* @author yqq
*
*/
private class LeaveInfoAdapter extends BaseAdapter{
@Override
public int getCount() {
// TODO Auto-generated method stub
return mleaveInfos.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return mleaveInfos.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) {
View view=null;
ViewHolder holder=null;
if (convertView!=null && convertView instanceof LinearLayout) {
view=convertView;
holder=(ViewHolder) view.getTag();
}else{
view=View.inflate(getApplicationContext(), R.layout.leave_info_item, null);
holder=new ViewHolder();
holder.name=(TextView)view.findViewById(R.id.tv_name);
holder.workIdAndDepartment=(TextView)view.findViewById(R.id.tv_workid_depart);
holder.leaveinfo=(TextView)view.findViewById(R.id.tv_leave_info);
holder.date=(TextView)view.findViewById(R.id.tv_date);
holder.endDate=(TextView)view.findViewById(R.id.tv_endtime);
view.setTag(holder);
}
LeaveInfo info=mleaveInfos.get(position);
Log.i("测试",info.toString());
holder.name.setText(info.getName());
holder.workIdAndDepartment.setText("(工号:"+info.getWorkId()+"部门:"+info.getDepartment()+")");
holder.leaveinfo.setText(info.getLeaveInfo());
holder.date.setText("假期起止:"+info.getLeaveData()+"\n");
holder.endDate.setText("-"+info.getEndleaveDate());
return view;
}
}
private static class ViewHolder{
TextView name;//员工姓名显示控件
TextView workIdAndDepartment;//员工工号和部门显示
TextView leaveinfo;//员工请假信息
TextView date;//员工请假日期
TextView endDate;
}
2、每项数据显示的布局
leave_info_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<ImageView
android:id="@+id/iv_headcolor"
android:layout_width="wrap_content"
android:layout_height="80dp"
android:src="@drawable/light_green" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp" >
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="姓名"
android:textColor="#ff0000"
android:textSize="15sp" />
<TextView
android:id="@+id/tv_leave_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_name"
android:paddingTop="8dp"
android:text="请假理由"
android:textSize="20sp" />
<TextView
android:id="@+id/tv_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/tv_leave_info"
android:layout_alignParentRight="true"
android:text="日期"
android:textColor="#000000"
android:textSize="10sp" />
<TextView
android:id="@+id/tv_endtime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_date"
android:layout_alignParentRight="true"
android:text="日期2"
android:textColor="#000000"
android:textSize="10sp" />
<TextView
android:id="@+id/tv_workid_depart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/tv_name"
android:gravity="center_horizontal"
android:paddingLeft="5dp"
android:text="姓名和部门"
android:textColor="#0000ff"
android:textSize="13sp" />
</RelativeLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@android:drawable/divider_horizontal_dark"
/>
</LinearLayout>
3、利用异步任务加载数据
/**
* 使用异步加载数据,填充待处理请假信息listView
*/
private void fillData(){
new AsyncTask<Void,Void,Void>() {
@Override
protected void onPostExecute(Void result) {
if(mAdapter==null){
mAdapter=new LeaveInfoAdapter();
//设置数据适配器
mLVleaveInfos.setAdapter(mAdapter);
Log.i("测试", "异步任务显示后台获得数据库数据");
}
else {
mAdapter.notifyDataSetChanged();
}
super.onPostExecute(result);
}
@Override
protected Void doInBackground(Void... params) {
//获得要显示的数据
mleaveInfos=mLeaveInfosDao.findAll();
if (mleaveInfos==null) {
Toast.makeText(HomeActivity.this,"请假数据不存在或是已经清除!", 500).show();
}
Log.i("测试", "异步任务后台获得数据库数据"+mleaveInfos.size());
return null;
}
}.execute();
}
4、为列表每项绑定事件监听
mLVleaveInfos.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Object object=mLVleaveInfos.getItemAtPosition(position);
Log.i("同意测试",object+"");
if(object instanceof LeaveInfo){
tmpInfo=(LeaveInfo)object;
Log.i("同意测试",tmpInfo.toString());
showAcceptOrNo();
}
}});
5、列表的其他监听和分页加载对于本地数据不需要分页加载,对于服务器端数据应该分页加载节省流量。
//下拉列表的时候分页加载数据
mRubishSms.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
//在下拉列表空闲的时候显示数据
case OnScrollListener.SCROLL_STATE_IDLE:
//获得分页加载的每页最大值
int position=mRubishSms.getLastVisiblePosition();
int total=0;
if(mInfos!=null){
// total=maxNum;
total=mInfos.size();
}
if(position==total-1){
//到达该分页加载的末尾位置
offset+=maxNum;
if(offset>totalNums){
Toast.makeText(RubishSmsActivity.this,"数据已经加载完,没有更多的数据了...", 300).show();
return;
}
//异步任务加载数据
fillData();
}
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
});
fillData();
//每个条目绑定监听
mRubishSms.setOnItemClickListener(new OnItemClickListener() {
View m_view=View.inflate(RubishSmsActivity.this,R.layout.show_rubish_sms_operation,null);
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//获得条目对应的每个对象
Object object=mRubishSms.getItemAtPosition(position);
if(object instanceof RubishSmsInfo){
final RubishSmsInfo info=(RubishSmsInfo) object;
//对对象的操作1、删除2、恢复到收件箱3、加入黑名单
Dialog builder=new Dialog(RubishSmsActivity.this);
builder.setTitle("提示");
builder.setContentView(m_view);
//删除
((TextView)m_view.findViewById(R.id.tv_delete)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mInfos.remove(info);
if(mRubishSmsInfoDao==null){
mRubishSmsInfoDao=new RubishSmsInfoDao(getApplicationContext());
}
mRubishSmsInfoDao.deleteSmsInfos(info);
if(mAdapter==null){
mAdapter=new RubishSmsInfosAdapter();
mRubishSms.setAdapter(mAdapter);
}else{
mAdapter.notifyDataSetChanged();
}
}
});
//恢复到收件箱
((TextView)m_view.findViewById(R.id.tv_recovery_sms)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
});
//加入黑名单
((TextView)m_view.findViewById(R.id.tv_add_black_number)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
});
builder.show();
}
}
});
}
6、BaseExpandableListAdapter示例demo:
public class CommonNumberActivity extends Activity {
private ExpandableListView elv;
private List<String> groupNames;
private Map<Integer, List<String>> childrenCacheInfos;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
childrenCacheInfos = new HashMap<Integer, List<String>>();
setContentView(R.layout.activity_common_num);
elv = (ExpandableListView) findViewById(R.id.elv);
elv.setAdapter(new MyAdapter());
elv.setOnChildClickListener(new OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_DIAL);
String number = childrenCacheInfos.get(groupPosition).get(childPosition).split("\n")[1];
intent.setData(Uri.parse("tel:"+number));
startActivity(intent);
return false;
}
});
}
private class MyAdapter extends BaseExpandableListAdapter {
// 返回多少个分组
@Override
public int getGroupCount() {
// return CommonNumDao.getGroupCount();
groupNames = CommonNumDao.getGroupInfos();
return groupNames.size();
}
@Override
public int getChildrenCount(int groupPosition) {// 0 开始
List<String> childreninfos;
if (childrenCacheInfos.containsKey(groupPosition)) {
childreninfos = childrenCacheInfos.get(groupPosition);
} else {
childreninfos = CommonNumDao
.getChildrenInfosByPosition(groupPosition);
childrenCacheInfos.put(groupPosition, childreninfos);
}
return childreninfos.size();
}
@Override
public Object getGroup(int groupPosition) {
return null;
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return null;
}
@Override
public long getGroupId(int groupPosition) {
return 0;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return 0;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
TextView tv;
if(convertView!=null&&convertView instanceof TextView){
tv = (TextView) convertView;
}else{
tv = new TextView(getApplicationContext());
}
tv.setTextSize(25);
tv.setTextColor(Color.RED);
// tv.setText(" "+CommonNumDao.getGroupName(groupPosition));
tv.setText(" " + groupNames.get(groupPosition));
return tv;
}
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
TextView tv;
if(convertView!=null&&convertView instanceof TextView){
tv = (TextView) convertView;
}else{
tv = new TextView(getApplicationContext());
}
tv.setTextSize(18);
tv.setTextColor(Color.BLUE);
// tv.setText(CommonNumDao.getChildInfoByPosition(groupPosition,
// childPosition));
tv.setText(childrenCacheInfos.get(groupPosition).get(childPosition));
return tv;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
}
7、BaseAdapter数据适配器的另一种用法demo:
package com.example.yqqmobilesafe;
import com.example.yqqmobilesafe.cleanache.CleanCacheActivity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class OftenUseFunctionActivity extends Activity {
private boolean D=true;
private GridView mGridView;//常用功能显示
private GVAdapter mAdapter;
private String[] items={"清理加速","话费流量","骚扰拦截","防吸费","支付保镖","手机杀毒"};
private int[] icons={R.drawable.exam_frequently_used_tools_icon_clean,R.drawable.exam_frequently_used_tools_icon_net_traffic,R.drawable.exam_frequently_used_tools_icon_block_anoy,R.drawable.exam_frequently_used_tools_icon_costguard,R.drawable.exam_frequently_used_tools_icon_guardpay,R.drawable.exam_frequently_used_tools_icon_malware};
public OftenUseFunctionActivity() {
// TODO Auto-generated constructor stub
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tab_often_use_function);
//数据适配
mGridView=(GridView)this.findViewById(R.id.gv_home);
mAdapter=new GVAdapter();
mGridView.setAdapter(mAdapter);
setListener();
}
private void setListener() {
mGridView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
switch (position) {
case 0:
Intent intent=new Intent(OftenUseFunctionActivity.this,CleanCacheActivity.class);
startActivity(intent);
if(D){
Log.i("OftenUseFunctionActivity","清理加速");
}
break;
case 1:
if(D){
Log.i("OftenUseFunctionActivity","话费流量");
}
break;
case 2:
if(D){
Log.i("OftenUseFunctionActivity","骚扰拦截");
}
Intent intent2=new Intent(OftenUseFunctionActivity.this,StopAnonyActivity.class);
startActivity(intent2);
break;
case 3:
if(D){
Log.i("OftenUseFunctionActivity","防吸费");
}
break;
case 4:
if(D){
Log.i("OftenUseFunctionActivity","支付保镖");
}
break;
case 5:
Intent intent6=new Intent(OftenUseFunctionActivity.this,KillVirusActivity.class);
startActivity(intent6);
if(D){
Log.i("OftenUseFunctionActivity","手机杀毒");
}
break;
}
}
});
}
//采用功能的数据适配器
private class GVAdapter extends BaseAdapter{
@Override
public int getCount() {
// TODO Auto-generated method stub
return items.length;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view=View.inflate(OftenUseFunctionActivity.this,R.layout.home_item,null);
ImageView ivIcon=(ImageView) view.findViewById(R.id.iv_home_icon);
TextView tvFunName=(TextView) view.findViewById(R.id.tv_home_function_name);
ivIcon.setImageResource(icons[position]);
tvFunName.setText(items[position]);
return view;
}
}
static class ViewHolder{
ImageView ivIcon;//功能图标
TextView tvFunName;//功能描述
}
}
home_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="95dp"
android:gravity="center"
android:background="@drawable/grid_selector" >
<ImageView
android:layout_marginTop="5dp"
android:id="@+id/iv_home_icon"
android:layout_width="55dp"
android:layout_height="45dp"
/>
<TextView
android:layout_marginTop="5dp"
android:id="@+id/tv_home_function_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:gravity="center_vertical"
android:textColor="#000000"
android:textSize="20sp" />
</LinearLayout>