[Android]ListView的Adapter.getView()方法中延迟加载图片的优化

时间:2021-12-27 03:08:11

以下内容为原创,欢迎转载,转载请注明

来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4139998.html

举个例子吧,以好友列表为例

ListView中每个Item表示一个好友,每个好友中都有一个头像,需要从服务端加载到本地,然后显示在item中。

显然,启动加载图片的过程应该是在getView()方法中触发,启动一个线程,然后下载头像图片。这里使用我写的一个开源框架ImageLoaderSamplehttps://github.com/wangjiegulu/ImageLoaderSample)来加载图片,并实现内存缓存和本地缓存。

额--这里不再介绍ImageLoaderSample的用法了,给个传送门:http://www.cnblogs.com/tiantianbyconan/p/3574131.html

再来看看getView()方法的调用时机:

1. Adapter调用NotifyDataChanged的时候

2. ListView滚动时,也就是convertView不断复用的时候。

也就是说,每当ListView滚动时,getView()方法不断被调用,图片下载的过程不断地执行(当然,ImageLoaderSample中会有缓存,但是内存缓存时有限的,如果内存缓存中找不到要显示的图片,那就需要到文件缓存中查找,需要进行io读写,这个也是相对比较耗时的),显然,这里面还有优化的余地。

怎么去优化这里?只要让ListView滚动的时候图片显示的时候不要去进行io读写就好了,具体逻辑如下:

-如果调用GetView方法时,ListView处于停止状态,则先去内存中查找头像图片;如果内存图片存在,则显示内存中保存好的图片;如果内存图片不存在,则继续到文件缓存中找,如果文件缓存图片存在,则显示文件缓存中的图片;如果文件缓存图片不存在,则根据url去网络下载这张图片,然后显示;

-如果调用getView方法时,ListView处于滚动状态,则去内存中查找头像的图片;如果内存图片存在,则显示内存中保存好的图片;如果内存图片不存在,则显示一张默认的图片(省去了从文件缓存中找图片和网络中去请求图片的步骤)。

这样的话,我们就必须要改写BaseAdapter,让它能够监测ListView的滚动状态,并在Adapter中可以获取到当前ListView的滚动状态。所以改造BaseAdapter,ABaseAdapterhttps://github.com/wangjiegulu/AndroidBucket/blob/master/src/com/wangjie/androidbucket/adapter/ABaseAdapter.java):

 package com.wangjie.androidbucket.adapter;

 import android.widget.*;
import com.wangjie.androidbucket.adapter.listener.OnAdapterScrollListener; /**
* Author: wangjie
* Email: tiantian.china.2@gmail.com
* Date: 12/3/14.
*/
public abstract class ABaseAdapter extends BaseAdapter implements AbsListView.OnScrollListener {
private OnAdapterScrollListener onAdapterScrollListener;
/**
* 当前listview是否属于滚动状态
*/
private boolean isScrolling; public boolean isScrolling() {
return isScrolling;
} public void setOnAdapterScrollListener(OnAdapterScrollListener onAdapterScrollListener) {
this.onAdapterScrollListener = onAdapterScrollListener;
} protected ABaseAdapter(AbsListView listView) {
listView.setOnScrollListener(this);
} @Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (null != onAdapterScrollListener) {
onAdapterScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
} @Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (null != onAdapterScrollListener) {
onAdapterScrollListener.onScrollStateChanged(view, scrollState);
} // 设置是否滚动的状态
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) { // 不滚动状态
isScrolling = false;
this.notifyDataSetChanged();
} else {
isScrolling = true;
}
}
}

如上述代码所示,该Adapter实现了AbsListView.OnScrollListener,并在构造方法中给ListView绑定了OnScrollListener,在实现的onScrollStateChanged方法中获取到当前滚动状态,并且保存这个状态isScrolling,并暴露isScrolling()方法给外面。

OnAdapterScrollListener这个接口是继承了AbsListView.OnScrollListener,因为这里在Adapter中一景设置了OnScrollListener了,所以如果在外面设置了新的OnScrollListener的话,就会失效了,所以必须提供另外一个setOnAdapterScrollListener,然后再传入一个OnScrollListener,然后在每个方法中进行回调就好了,因为考虑到以后可能会扩展其他的接口方法,所以这里新写了一个接口(为了以后扩展时原来的代码不会被影响,推荐使用OnAdapterScrollSampleListener这个实现类来代替OnAdapterScrollListener这个接口,OnAdapterScrollSampleListener这个类只是对OnAdapterScrollListener的所有方法进行了空实现)。

然后我们编写一个MyAdapter继承ABaseAdapter,然后,在getView()方法中,需要显示头像的时候调用如下方法:

// 如果在滚动(从内存中查找,找不到也不进行网络请求)

ImageLoader.getInstances().displayImage(headUrl, headIv, null, R.drawable.default_head, isScrolling());

看到木有?

1. displayImage()方法发生了改变,多了最后一个参数isOnlyMemory这个参数,表示是否只是在内存缓存中找这张图片,如果没有就不再继续找下去了(displayImage原来的方法我还留着,所以不会影响之前的代码)。

2. 调用了isScrolling()方法,作为参数isOnlyMemory的值,表示,如果正在滚动的话,就只在缓存中找这张图片。

这样,运行原来的代码试试吧,是不是效率快了一些?

[Android]ListView的Adapter.getView()方法中延迟加载图片的优化的更多相关文章

  1. Android LIstView初次创建getview方法执行多次问题

    写listview优化的时候,发现Listview初次创建的时候会多次执行getView方法. <?xml version="1.0" encoding="utf- ...

  2. Android listview与adapter用法&lpar;BaseAdapter &plus; getView&rpar;

    Android listview与adapter用法http://www.cnblogs.com/zhengbeibei/archive/2013/05/14/3078805.html package ...

  3. Android listview与adapter用法

    listview与adapter用法 博客分类: android   一个ListView通常有两个职责. (1)将数据填充到布局. (2)处理用户的选择点击等操作. 第一点很好理解,ListView ...

  4. 【转】Android listview与adapter用法

    一个ListView通常有两个职责. (1)将数据填充到布局. (2)处理用户的选择点击等操作. 第一点很好理解,ListView就是实现这个功能的.第二点也不难做到,在后面的学习中读者会发现,这非常 ...

  5. android Listview 软引用SoftReference异步加载图片

    首先说一下,android系统加载大量图片系统内存溢出的3中解决方法: (1)从网络或本地加载图片的时候,只加载缩略图.这个方法的确能够少占用不少内存,可是它的致命的缺点就是,因为加载的是缩略图,所以 ...

  6. &lbrack;Android&rsqb;在Adapter的getView方法中绑定OnClickListener比较好的方法

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4146512.html  给ListView中每个item绑定点 ...

  7. Android -- ListView与Adapter

    ListView在Android中有着很重要的作用.Android开发中ListView是比较常用的组件,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示. 背景              ...

  8. Android ListView 和 &ast;&ast;&ast;Adapter 从本地&sol;网络获取歌曲列表

    本文内容 环境 项目结构 测试数据 演示 1:SimpleAdapter 演示 2:BaseAdapter 演示 3:CustomLazyList 演示 4:CustomLazyCompleteLis ...

  9. android listview用adapter&period;notifyDataSetChanged&lpar;&rpar;无法刷新每项的图标

    http://blog.csdn.net/caizhegnhao/article/details/41318575 今天在开发中遇到一个很奇怪的listview的问题. 这个问题情景是我的应用需要做一 ...

随机推荐

  1. hdu 1570 AC

    A C Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  2. 【枚举&plus;贪心】【TOJ3981】【ICPC Balloons】

    给你N种不同颜色气球,每种气球有个数目 count[i],给的同种颜色气球可能是L尺寸,或M尺寸. M个问题,每个问题有个解决人数ac[i]. 每个问题 要分配一种颜色的气球,尺寸要一样 现在 这些气 ...

  3. &lbrack;LeetCode62&rsqb;Unique Paths

    题目: A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). ...

  4. zcu102 hdmi example(一)

    1,概述 有一个计划是打算做一个摄像头的驱动与显示. 但是实际上手上只有一个zcu102开发板,没有摄像头,也没有上位机,自己也不会写.所以就将方案阉割成将录制好的视频放在SD卡里面,然后从SD卡里面 ...

  5. tomat startup&period;bat 日志乱码问题解决

    1.修改conf 下的logging.properties java.util.logging.ConsoleHandle.encoding=GBK C:\Users\Administrator&gt ...

  6. 数据库相关--net start mysql 服务无法启动(win7系统)解决

    系统:win7 旗舰版 64位 MySQL:8.0.11 家里台式机上不久之前安装了MySQL,一段时间没碰过后,突然启动不了了(我有一头小毛驴,我从来也不骑,有一天我心血来潮骑它去赶集) 先是在系统 ...

  7. 改装原生的dialog

    改装 dialog 定制 View rootView = LayoutInflater.from(mContext). inflate(R.layout.nfc_tag_name_dialog, nu ...

  8. 重复打印相同内容&lpar;Doc档&rpar;的时候自动生成打印编号

    昨天突然接到一个好久未联系的朋友电话,说是江湖救急,要打印一份单据,单据上有个号码要自动生成,如下图,最土的办法是打印完一张,手工改下号码,但这种方法估计碰到成百上千张时估计会疯掉 网上找了实现方法, ...

  9. synchronized、Lock、ReentrantLock、ReadWriteLock

    synchronized:同步锁,是java内置的关键字.当一个线程A执行到被synchronized修饰的方法时,其他线程B如果也要执行这个方法,那么B只能等A执行完方法释放锁后才能获取资源锁执行s ...

  10. OpenResty 高阶实战之————Redis授权登录使用短连接&lpar;5000&rpar;和长连接&lpar;500W&rpar; 使用连接池AB压力测试结果

    一.短连接开始测试 ab -n 5000 -c 100 -k 127.0.0.1/test_redis_short #demo1 Concurrency Level: Time taken for t ...