之前接触了ListView和Adapter,Adapter将数据源和View连接起来,实际应用中,我们要显示的数据往往有很多,而屏幕只有那么大,系统只能屏幕所能显示的内容,当我们滑动屏幕,会将旧的内容放入到缓冲池中,再从缓存池中拿出新的内容显示出来,这就是ListView的缓存机制,这一机制可以极大的节省系统资源。

BaseAdapter

BaseAdapter通常用于被扩展,扩展BaseAdapter可以对各项列表进行最大限度的定制。

我们可以用自己的类去继承BaseAdapter,然后实现getCount()、getItem()、getItemId()、getView()这四个方法,来完成对Adapter的定制。

getCount()    该方法返回ListView需要显示的数据量

getItem()      该方法返回指定索引(position)所对应的数据项

getItemId()  该方法返回对应的索引

getView()      该方法返回每一项所显示的内容

简单示例:

package cn.lixyz.baseadaptertest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast; import java.util.ArrayList;
import java.util.List; public class MainActivity extends AppCompatActivity { List<ItemBean> itemBeanList;
ListView listView; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); itemBeanList = new ArrayList<ItemBean>();
for (int i = 0; i < 20; i++) {
ItemBean ib = new ItemBean(R.drawable.icon, "标题" + i, "内容" + i);
itemBeanList.add(ib);
} listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(new MyAdapter(this, itemBeanList)); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MainActivity.this, "你选择的是:" + position, Toast.LENGTH_SHORT).show();
}
}); }
}

MainActivity.java

<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity"> <ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" /> </LinearLayout>

layout_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <ImageView
android:id="@+id/iv_icon"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:src="@drawable/icon" /> <TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_marginTop="10dp"
android:layout_toEndOf="@+id/iv_icon"
android:gravity="center"
android:text="标题"
android:textSize="25dp" /> <TextView
android:id="@+id/tv_desc"
android:layout_width="match_parent"
android:layout_height="25dp"
android:layout_below="@+id/tv_name"
android:layout_marginLeft="10dp"
android:layout_toEndOf="@+id/iv_icon"
android:gravity="center"
android:text="内容内容内容内容" /> </RelativeLayout>

layout_item.xml

package cn.lixyz.baseadaptertest;

/**
* Created by LGB on 2015/9/9.
*/
public class ItemBean {
public int ItemImageResid;
public String ItemName;
public String Itemdesc; public ItemBean(int ItemImageResid, String ItemName, String Itemdesc) {
this.ItemImageResid = ItemImageResid;
this.ItemName = ItemName;
this.Itemdesc = Itemdesc;
}
}

ItemBean.java

package cn.lixyz.baseadaptertest;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView; import java.util.List; /**
* Created by LGB on 2015/9/9.
*/
public class MyAdapter extends BaseAdapter { private List<ItemBean> list;
private LayoutInflater inflater; public MyAdapter(Context context, List<ItemBean> list) {
this.list = list;
inflater = LayoutInflater.from(context);
} //该方法返回ListView需要显示的数据量
@Override
public int getCount() {
return list.size();
} //该方法返回指定索引(position)所对应的数据项
@Override
public Object getItem(int position) {
return list.get(position);
} //该方法返回对应的索引
@Override
public long getItemId(int position) {
return 0;
} //
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = inflater.inflate(R.layout.laytou_item, null);
ImageView imageView = (ImageView) view.findViewById(R.id.iv_icon);
TextView name = (TextView) view.findViewById(R.id.tv_name);
TextView desc = (TextView) view.findViewById(R.id.tv_desc); imageView.setImageResource(list.get(position).ItemImageResid);
name.setText(list.get(position).ItemName);
desc.setText(list.get(position).Itemdesc); return view;
}
}

MyAdapter.java

运行结果:

上面的代码中,我们可以看到一个ListView中的每一项都是我们直接使用Inflater新建并返回的,完全没有使用到ListView提供的缓存机制

View view = inflater.inflate(R.layout.laytou_item, null);
......
return view;

有关inflater的内容,可以看这里:<转> Android LayoutInflater详解      Android 中LayoutInflater的使用

我们稍对代码做一下修改:

package cn.lixyz.baseadaptertest;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView; import java.util.List; /**
* Created by LGB on 2015/9/9.
*/
public class MyAdapter extends BaseAdapter { private List<ItemBean> list;
private LayoutInflater inflater; public MyAdapter(Context context, List<ItemBean> list) {
this.list = list;
inflater = LayoutInflater.from(context);
} //该方法返回ListView需要显示的数据量
@Override
public int getCount() {
return list.size();
} //该方法返回指定索引(position)所对应的数据项
@Override
public Object getItem(int position) {
return list.get(position);
} //该方法返回对应的索引
@Override
public long getItemId(int position) {
return 0;
} //该方法返回每一项所显示的内容
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.laytou_item, null);
}
ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_icon);
TextView name = (TextView) convertView.findViewById(R.id.tv_name);
TextView desc = (TextView) convertView.findViewById(R.id.tv_desc); imageView.setImageResource(list.get(position).ItemImageResid);
name.setText(list.get(position).ItemName);
desc.setText(list.get(position).Itemdesc);
return convertView;
}
}

我们先判断要显示的view是否已经存在,如果不存在,才创建,如果存在,就直接返回,这样也就避免了多次重复创建。

现在避免了多次创建View对象了,但是每次调用getView的时候,仍然会多次使用findViewById来创建组件,那么有没有办法可以避免在这个问题上面浪费资源呢,这里就使用到了view的getTag和setTag,通常我们会创建一个ViewHolder类然后实例化,然后通过setTag的方法将这个ViewHolder对象和View连接起来

看代码:

package cn.lixyz.baseadaptertest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast; import java.util.ArrayList;
import java.util.List; public class MainActivity extends AppCompatActivity { List<ItemBean> itemBeanList;
ListView listView; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); itemBeanList = new ArrayList<ItemBean>();
for (int i = 0; i < 20; i++) {
ItemBean ib = new ItemBean(R.drawable.icon, "标题" + i, "内容" + i);
itemBeanList.add(ib);
} listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(new MyAdapter(this, itemBeanList)); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MainActivity.this, "你选择的是:" + position, Toast.LENGTH_SHORT).show();
}
}); }
}

MainActivity.java

<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity"> <ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" /> </LinearLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <ImageView
android:id="@+id/iv_icon"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp" /> <TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_marginTop="10dp"
android:layout_toEndOf="@+id/iv_icon"
android:gravity="center"
android:text="标题"
android:textSize="25dp" /> <TextView
android:id="@+id/tv_desc"
android:layout_width="match_parent"
android:layout_height="25dp"
android:layout_below="@+id/tv_name"
android:layout_marginLeft="10dp"
android:layout_toEndOf="@+id/iv_icon"
android:gravity="center"
android:text="内容内容内容内容" /> </RelativeLayout>

layout_item.xml

package cn.lixyz.baseadaptertest;

/**
* Created by LGB on 2015/9/9.
*/
public class ItemBean {
public int ItemImageResid;
public String ItemName;
public String Itemdesc; public ItemBean(int ItemImageResid, String ItemName, String Itemdesc) {
this.ItemImageResid = ItemImageResid;
this.ItemName = ItemName;
this.Itemdesc = Itemdesc;
}
}

ItemBean.java

package cn.lixyz.baseadaptertest;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView; import java.util.List; /**
* Created by LGB on 2015/9/9.
*/
public class MyAdapter extends BaseAdapter { private List<ItemBean> list;
private LayoutInflater inflater; public MyAdapter(Context context, List<ItemBean> list) {
this.list = list;
inflater = LayoutInflater.from(context);
} //该方法返回ListView需要显示的数据量
@Override
public int getCount() {
return list.size();
} //该方法返回指定索引(position)所对应的数据项
@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) {
ViewHolder vh = null;
if (convertView == null) {
vh = new ViewHolder();
convertView = inflater.inflate(R.layout.laytou_item, null);
vh.imageView = (ImageView) convertView.findViewById(R.id.iv_icon);
vh.name = (TextView) convertView.findViewById(R.id.tv_name);
vh.desc = (TextView) convertView.findViewById(R.id.tv_desc);
convertView.setTag(vh);
} else {
vh = (ViewHolder) convertView.getTag();
} vh.imageView.setImageResource(list.get(position).ItemImageResid);
vh.name.setText(list.get(position).ItemName);
vh.desc.setText(list.get(position).Itemdesc); return convertView;
} //创建ViewHolder,避免重复的findViewById操作浪费资源
class ViewHolder {
public ImageView imageView;
public TextView name;
public TextView desc;
}
}

MyAdapter.java

运行结果是一样的

在上面的代码中,我们创建了一个ViewHolder对象,用来保存一个Item的内容,然后使用setTag()将View和ViewHolder对象连接起来,假如convertView不为空的话,直接使用getTag来获取View对象,然后再给这个对象的属性赋值(也就是给Item的组件赋值),这样就充分利用了ListView的缓存机制,避免重复findViewById造成资源的浪费

总结一下使用ListView缓存机制的思路

1)创建Bean对象,用户封装数据ItemBean

2)在构造方法中初始化用户映射的数据List

3)创建ViewHolder类,创建布局映射关系

4)判断convertView是否为空,如果为空,则创建,并设置tag,如果不为空,则通过getTag来去除ViewHolder

5)给ViewHolder中的控件设置数据

Android笔记(二十五) ListView的缓存机制与BaseAdapter的更多相关文章

  1. python3.4学习笔记(二十五) Python 调用mysql redis实例代码

    python3.4学习笔记(二十五) Python 调用mysql redis实例代码 #coding: utf-8 __author__ = 'zdz8207' #python2.7 import ...

  2. Django框架(二十八)—— Django缓存机制

    目录 Django缓存机制 一.什么是缓存 二.Django的6中缓存方式及配置(只需要改配置文件) 1.开发调试缓存(此模式为开发调试使用,实际上不执行任何操作) 2.内存缓存(将缓存内容保存至内存 ...

  3. Java基础学习笔记二十五 MySQL

    MySQL 在dos中操作mysql 连接mysql命令: mysql -uroot -p密码 ,连接OK,会出现mysql> 对数据库的操作 创建一个库 create database 库名 ...

  4. Android笔记二十四.Android基于回调的事件处理机制

        假设说事件监听机制是一种托付式的事件处理,那么回调机制则与之相反,对于基于回调的事件处理模型来说,事件源和事件监听器是统一的,或者说事件监听器全然消失了,当用户在GUI控件上激发某个事件时,控 ...

  5. 论文阅读笔记二十五:Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition(SPPNet CVPR2014)

    论文源址:https://arxiv.org/abs/1406.4729 tensorflow相关代码:https://github.com/peace195/sppnet 摘要 深度卷积网络需要输入 ...

  6. Android笔记(十)ListView

    ListView是Android中最经常使用的控件之中的一个,也是最难用的控件. ListView的作用是展示大量的数据,只是ListView并非直接和数据打交道.而是通过适配器作为中间桥梁. 1.首 ...

  7. Java学习笔记二十五:Java面向对象的三大特性之多态

    Java面向对象的三大特性之多态 一:什么是多态: 多态是同一个行为具有多个不同表现形式或形态的能力. 多态就是同一个接口,使用不同的实例而执行不同操作. 多态性是对象多种表现形式的体现. 现实中,比 ...

  8. Android笔记(七十五) Android中的图片压缩

    这几天在做图记的时候遇第一次遇到了OOM,好激动~~ 追究原因,是因为在ListView中加载的图片太大造成的,因为我使用的都是手机相机直接拍摄的照片,图片都比较大,所以在加载的时候会出现内存溢出,那 ...

  9. Android进阶(二十五)setTextColor()的参数设置方式

    setTextColor()的参数设置方式 查了下资料发现setTextColor()的参数可以写成以下形式: 直接使用颜色值 setTextColor(0xFF0000FF);//0xFF0000F ...

随机推荐

  1. NativeExcel3使用示例

    除了XLSReadWriteII5,还有个NativeExcel也是比较好的操作excel的组件,现将NativeExcel3的使用示例写一下,以下是代码和生成的excel表格的效果: procedu ...

  2. C# WinForm获取 当前执行程序路径的几种方法(转)

    1.获取和设置当前目录的完全限定路径. string str = System.Environment.CurrentDirectory; Result: C:xxxxxx 2.获取启动了应用程序的可 ...

  3. npm publish 一直报错 404

    在封装 zswui  react ui 组件库的时候,尝试了下 github的 packages 包设置,然后就给自己挖坑了. zswui   这是一个从零开始配置,实现组件开发测试的项目. 因为设置 ...

  4. Git出现There is no tracking information for the current branch提示的解决办法

    参考:https://blog.csdn.net/sinat_36246371/article/details/79738782 在执行git pull的时候,提示当前branch没有跟踪信息: Th ...

  5. 01点睛Spring MVC 4.1-搭建环境

    转发:https://www.iteye.com/blog/wiselyman-2213906 1.1 简单示例 通篇使用java config @Controller声明bean是一个控制器 @Re ...

  6. DevOps - 配置管理工具Ansible

    1 - 配置管理工具 配置管理工具(SCM,Software Configuration Management)可以将代码.软件方式实现的基础设施配置信息保存,也可以根据需求变化反复进行变更. 相关工 ...

  7. git 版本控制中回溯到某个历史版本

    1.git log 查看之前的版本号 2. git reset --hard 版本号 3.git push -f -u origin 分支 恢复上一个版本是: git reset --hard HEA ...

  8. 方法重载overload与方法重写overwrite

    方法重载overload: 在同一个类中,出现相同的方法名,与返回值无关,参数列表不同:1参数的个数不同 2参数类型不同 在调用方法时,java虚拟机会通过参数列表来区分不同同名的方法 方法重写ove ...

  9. Suspended Animation——《The Economist》阅读积累(考研英语二·2010 Reading Text 1)

    [知识小百科] Damien Hirst(达米恩●赫斯特):生于1965年,是新一代英国艺术家的主要代表人物之一.他主导了90年代英国艺术发展并享有很高的国际声誉.赫斯特在1986年9月就读于伦敦大学 ...

  10. ubuntu gcc 安装 使用

    "人多不足以依赖,要生存只有靠自己." -- 拿破仑 gcc是什么:-------------------------- Linux系统下的Gcc(GNU C Compiler)是 ...