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. 关于在WIN32调用一些Zw系列的文件操作函数

    转自:http://blog.csdn.net/cooblily/archive/2007/10/27/1848037.aspx 都好久沒上來写文章了,都不知道做什么好,結果还是学写了一下用Nativ ...

  2. android:layout_weight详解

    参考; www.cnblogs.com/alpha-bowen/archive/2011/03/02/1969343.html 总结: 当需要对页面按比例分配时会用到这个选项: layout_weig ...

  3. jni.h头文件详解一

    1.jni.h头文件路径: /usr/lib/jvm/jdk_1.6.0_43/include/jni.h 2.jni.h头文件组成分析图: 3.下面通过上图进行分析讲解jni.h头文件. 一. jn ...

  4. 利用if else来运行咱们结婚吧

    static void Main(string[] args)        {            while (true)            {                string ...

  5. bzoj1085

    肯定是搜索题无疑问, 首先要求在15步以内(包括15步)到达目标状态,也就是限定了搜索的深度,于是我们用dfs更合适 但这样复杂度仍然太大,原因就是我们在搜索中做了很多很不优的尝试 考虑当前状态若与目 ...

  6. Hadoop RPC源码阅读-交互协议

    Hadoop版本Hadoop2.6 RPC主要分为3个部分:(1)交互协议(2)客户端 (3)服务端 (1)交互协议 协议:把某些接口和接口中的方法称为协议,客户端和服务端只要实现这些接口中的方法就可 ...

  7. android webview js交互 第一节 (java和js交互)

    转载请注明出处         挺帅的移动开发专栏  http://blog.csdn.net/wangtingshuai/article/details/8631835        在androi ...

  8. Linux route命令详解和使用示例(查看和操作IP路由表)

    Linux系统的route命令用于显示和操作IP路由表(show / manipulate the IP routing table).要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器,或 ...

  9. 如何实现批处理文件传参数给SQLPLUS

    原文地址:http://www.cnblogs.com/HondaHsu/archive/2012/11/23/2784094.html 第一:批处理文件drop_table.bat 说明: 批处理中 ...

  10. HDOJ/HDU 2564 词组缩写(单词缩写)

    Problem Description 定义:一个词组中每个单词的首字母的大写组合称为该词组的缩写. 比如,C语言里常用的EOF就是end of file的缩写. Input 输入的第一行是一个整数T ...