BaseAdapter是一个数据适配器,将我们提供的数据格式化为ListView可以显示的数据,BaseAdapter的优化直接影响到ListView的显示效率。

我们都知道,ListView自带有回收机制,当一个Item滑出屏幕的时候,ListView会自动把这个ListView回收到缓冲区,当有一个Item滑入屏幕的时候,ListView会自动从缓冲区读取一个Item,并给它赋上值,然后显示出来,这便是ListView的回收机制,然而,如果你在BaseAdapter中没有做相应的优化,你的程序有可能根本就没有使用ListView的回收机制,这将会造成很大的资源浪费。好了,下来我们看看BaseAdater的优化问题。


  • 第一步:新建项目并且准备数据

    1.新建一个android项目,修改主布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.baseadapter.MainActivity" >
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/listview"
></ListView>
</RelativeLayout>

2.在MainActivity中对数据进行初始化:

public class MainActivity extends Activity {

    private ListView listView;
private List<Person> list; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) this.findViewById(R.id.listview);
initData();
MyAdapter adapter = new MyAdapter(this,list);
listView.setAdapter(adapter);
} private void initData() {
list = new ArrayList<Person>();
Person p = null;
for (int i = 0; i < 100; i++) {
p = new Person("zhangsan" + i, i, "张三" + i);
list.add(p);
}
}
}

由于我们把Adapter单独抽取成了一个类,因此要通过构造方法来传递上下文和数据两个参数。

再来一个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="wrap_content"
android:orientation="horizontal"
>
<TextView
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
<TextView
android:id="@+id/nickname"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
<TextView
android:id="@+id/age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/> </LinearLayout>

  • 第二步:简单的使用

    先来看看最简单的用法,即我们不使用ListView的回收机制,也不做任何优化,看看显示效果,前面三个方法和我们平时用的时候都是一样的,不做过多说明,重点是getView方法,在getView方法中,我们每次都重新获得一个新的view,很明显,这种方式简单粗暴,效率低下,而且除了getView方法中的position参数之外,其他的参数我们都没有用到。
    @Override
public int getCount() {
return list.size();
} @Override
public Object getItem(int position) {
return list.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
//简单使用
View v = new View(context);
TextView username = (TextView) v.findViewById(R.id.username);
TextView nickname = (TextView) v.findViewById(R.id.nickname);
TextView age = (TextView) v.findViewById(R.id.age);
username.setText(list.get(position).getUsername());
nickname.setText(list.get(position).getNickname());
age.setText(list.get(position).getAge()+"");
return v;
}

  • 第三步:使用回收机制

    上面一种方式没有使用任何的回收策略,现在我们就来解决这个问题,看看怎么使用ListView中的回收机制。这里,我们在每次使用View之前都先判断view是否为空,为空的话我们再重新获得一个View,否则就使用之前的view.
    @Override
public View getView(int position, View convertView, ViewGroup parent) {
// 简单使用
// View v = LayoutInflater.from(context).inflate(R.layout.item, null);
// TextView username = (TextView) v.findViewById(R.id.username);
// TextView nickname = (TextView) v.findViewById(R.id.nickname);
// TextView age = (TextView) v.findViewById(R.id.age);
// username.setText(list.get(position).getUsername());
// nickname.setText(list.get(position).getNickname());
// age.setText(list.get(position).getAge()+""); // 使用ListView回收机制
if (convertView == null)
convertView = LayoutInflater.from(context).inflate(R.layout.item,
null);
TextView username = (TextView) convertView.findViewById(R.id.username);
TextView nickname = (TextView) convertView.findViewById(R.id.nickname);
TextView age = (TextView) convertView.findViewById(R.id.age);
username.setText(list.get(position).getUsername());
nickname.setText(list.get(position).getNickname());
age.setText(list.get(position).getAge()+"");
return convertView;
}

  • 第四步:减少findViewById的使用

上面已经解决了回收item的问题,但是每次都要findViewById依然是非常耗时,所以这里我们将要使用一个ViewHolder来解决这个问题。所有item中的控件我们都在ViewHolder这个类中来说明,然后在实例化convertView的时候把ViewHolder保存在convertView中,在后面的使用中直接从convertView中获得ViewHolder。这样就避免了每次findViewById,尽量节省显示时间。

    @Override
public View getView(int position, View convertView, ViewGroup parent) {
// 简单使用
// View v = LayoutInflater.from(context).inflate(R.layout.item, null);
// TextView username = (TextView) v.findViewById(R.id.username);
// TextView nickname = (TextView) v.findViewById(R.id.nickname);
// TextView age = (TextView) v.findViewById(R.id.age);
// username.setText(list.get(position).getUsername());
// nickname.setText(list.get(position).getNickname());
// age.setText(list.get(position).getAge()+""); // 使用ListView回收机制
// if (convertView == null)
// convertView = LayoutInflater.from(context).inflate(R.layout.item,
// null);
// TextView username = (TextView)
// convertView.findViewById(R.id.username);
// TextView nickname = (TextView)
// convertView.findViewById(R.id.nickname);
// TextView age = (TextView) convertView.findViewById(R.id.age);
// username.setText(list.get(position).getUsername());
// nickname.setText(list.get(position).getNickname());
// age.setText(list.get(position).getAge()+""); // 终极版
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.item,
null);
viewHolder.username = (TextView) convertView
.findViewById(R.id.username);
viewHolder.nickname = (TextView) convertView
.findViewById(R.id.nickname);
viewHolder.age = (TextView) convertView.findViewById(R.id.age);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.username.setText(list.get(position).getUsername());
viewHolder.nickname.setText(list.get(position).getNickname());
viewHolder.age.setText(list.get(position).getAge() + "");
return convertView;
}

  • 第五布:三种方式比较

    上面我们介绍了三种方式,孰优孰劣,还是要数据说话,我们在getView开始和结束的时候加上时间统计方法,看看三种方式到底花费了多少时间。真是不比不知道,一比吓一跳。







    不使用回收机制真的太可怕了!!!

  • 总结

    为了使我们的程序获得良好的性能,建议大家使用上文中第四步介绍的方式来使用BaseAdapter。

本项目完整代码下载


版权声明:本文为博主原创文章,未经博主允许不得转载。若有错误地方,还望批评指正,不胜感激。

BaseAdapter优化深入分析的更多相关文章

  1. Android学习总结(十二)———— BaseAdapter优化

    一.BaseAdapter的基本概念 对于Android程序员来说,BaseAdapter肯定不会陌生,灵活而优雅是BaseAdapter最大的特点.开发者可以通过构造BaseAdapter并搭载到L ...

  2. Android编码学习之Adapter

    1. Apter的作用 Adapter是将数据绑定到UI界面上的桥接类.Adapter负责创建显示每个项目的子View和提供对下层数据的访问.Adapter的作用就是将要在列表内显示的数据和列表本身结 ...

  3. 02-11Android学习进度报告十一

    今天我学习了BaseAdapter优化的知识,主要是View方面的优化. 首先是复用复用ConvertView 代码示例: @Override public View getView(int posi ...

  4. Android关于listView的BaseAdapter以及getView的三级优化

    1.4个重写方法的含义 自定义Adapter继承自BaseAdapter(通用适配器)   getCount(); getItem(); getItemId(); getViewTypaCount() ...

  5. 深入分析PHP优化及注意事项

    深入分析PHP优化及注意事项 1.尽量静态化: 如果一个方法能被静态,那就声明它为静态的,速度可提高1/4,甚至我测试的时候,这个提高了近三倍. 当然了,这个测试方法需要在十万级以上次执行,效果才明显 ...

  6. 关于BaseAdapter的使用及优化心得(一)

    对于Android程序员来说,BaseAdapter肯定不会陌生,灵活而优雅是BaseAdapter最大的特点.开发者可以通过构造BaseAdapter并搭载到ListView或者GridView这类 ...

  7. 【Android】以BaseAdapter做适配器的ListView及其性能优化

    适配器的Java类 package com.app.adapter; import org.json.JSONArray; import org.json.JSONObject; import and ...

  8. BaseAdapter以及对ListView的优化(转)

    背景 对于ListView.GridView.Gallery.Spinner等等,它是它们的适配器,直接继承自接口类Adapter的,使用BaseAdapter时需要重写很多方法,其中最重要的当属ge ...

  9. Android中的自定义Adapter(继承自BaseAdapter)——与系统Adapter的调用方法一致——含ViewHolder显示效率的优化(转)

    Android中很多地方使用的是适配器(Adapter)机制,那我们就要好好把这个Adapter利用起来,并且用出自己的特色,来符合我们自行设计的需要喽~~~ 下面先上一个例子,是使用ViewHold ...

随机推荐

  1. textarea宽度、高度自动适应处理方法

    textarea自动高度 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http: ...

  2. Mysql Partition 理论知识总结

    简述: 本文内容主要 Giuseppe Maxia 曾在Mysql Conference & Expo 2010发表关于 <Mysql Partition in Mysql 5.1 &a ...

  3. SDUT 2351 In Danger

    点我看题目 题意 : 有n个兵想要自杀,所以他们决定围成一个圈,从1开始一直环到n,然后每第2个开始自杀,但是有一个兵不想死,所以让你编程求出最后一个应该死的人的位置,这样的话就剩他自己他可以不自杀了 ...

  4. Android 获取手机联系人信息

    //获取联系人 Uri rawContacts = Uri.parse("content://com.android.contacts/raw_contacts"); Conten ...

  5. CAS实现单点登录方案(SSO完整版)

    一.简介 1.cas是由耶鲁大学研发的单点登录服务器 2.本教材所用环境 Tomcat7.2 JDK1.7 CAS Service 版本    cas-server-3.4.8-release CAS ...

  6. RocketMQ在windows上安装和开发使用

    1.概述 RocketMQ是alibaba公司开源的一个纯java的开源消息中间件. 2.开发测试环境搭建 到github上面rocketMQ,我选择的是alibaba-rocketmq-3.2.6. ...

  7. ANDROID_MARS学习笔记_S05_004_过滤杂质,得到真正的加速度

    一.简介 二.代码1.java (1)MainActivity.java import android.app.Activity; import android.content.Context; im ...

  8. C++开发与Windows API

    Windows API 向 C++ 开发人员提出了一项挑战. 组成 API 的众多库大都表现为 C 语言风格的函数和句柄或是 COM 风格的接口. 这些用起来都不太方便,需要进行一定的封装或间接操作. ...

  9. 【Xamarin挖墙脚系列:Xamarin的核心】

    原文:[Xamarin挖墙脚系列:Xamarin的核心] Xamarin 包含两个商业产品 :Xamarin.IOS, Xamarin.Android.他们都是通过开源的基于.Net的Mono项目构建 ...

  10. linux ERROR: ld.so: object '/lib/libcwait.so' from /etc/ld.so.preload cannot be preloaded: ignored.

    [root@ora9i 3238244]# lsb_release -a LSB Version:    :core-3.0-amd64:core-3.0-ia32:core-3.0-noarch:g ...