Android ListView 图片异步加载和图片内存缓存

Android ListView图片加载优化:二级缓存技术实现 双缓存机制的优化流程大致可以概括如下:当请求加载数据时,首先查询内存缓存。如果内存缓存中存在所需的数据,则直接使用,无需从磁盘读取。如果内存缓存中不存在,则查询磁盘缓存。如果磁盘缓存中存在所需数据,则将数据从磁盘加载到内存中,以便快速访问。如果磁盘缓存也不存在该数据,则需要从网络或其他数据源进行加载,并同时将新数据存储到磁盘和内存中以备后用。这种优化流程通过减少不必要的磁盘I/O操作,加快了数据访问速度,同时提高了应用的响应性。 阅读详情

中间偷懒了,好久没有写博客了,今天写一下我研究了好几天的Android ListView 图片异步加载和图片内存缓存。嘿嘿。


开发Android应用经常需要处理图片的加载问题。因为图片一般都是存放在服务器端,需要联网去加载,而这又是一个比较耗时的过程,所以Android中都是通过开启一个异步线程去加载。为了增加用户体验,给用户省流量,一般把加载完的图片先缓存下来,下次加载的时候就不需要再联网去服务器端加载。图片缓存一般分为一级缓存(即内存缓存)和二级缓存(即磁盘缓存)。这里只讲一级缓存。

内存缓存就是把加载完的图片先放在手机内存中,等下次加载的时候再从内存中取出来。

优点是速度快,缺点是不能长久保存,用户退出应用程序之后内存缓存就被回收了。而且加载太多会抛出java.lang.OutOfMemory异常。

磁盘缓存就是把加载完的图片放到手机内置存储卡或SD卡中。下次加载的时候在从里面取出来。

优点是能够长期保存,缺点是速度较慢,为了不影响用户体验,也一般是通过异步线程去取磁盘中的缓存图片;还有一个就是用户卸载应用程序后这些缓存文件不会随着删除,浪费了用户的磁盘空间,需要用户手动删除。

     

图片缓存很多人都是用软引用SoftRReference来处理,但是Android官方并不推荐这么用。

Android官方给出的理由是:Note: In the past, a popular memory cache implementation was a SoftReference or WeakReference bitmap cache, however this is not recommended. Starting from Android 2.3 (API Level 9) the garbage collector is more aggressive with collecting soft/weak references which makes them fairly ineffective. In addition, prior to Android 3.0 (API Level 11), the backing data of a bitmap was stored in native memory which is not released in a predictable manner, potentially causing an application to briefly exceed its memory limits and crash.

        

所以我们一般使用LruCache这个类,这个类可以这样理解:它就是一个内存缓存对象,你的图片就缓存在这个类里面。(Java中什么都是对象)这个类是在API 12中才有的,不过幸运的是Android官方把它加入了v4包中,所以1.6以后的都可以使用这个类。这个类用起来也比较简单(官方文档上也讲的很详细)。

    

下面讲一下我是怎样用的:

首先是给ListView 自定义一个Adapter(继承自BaseAdapter),然后在这个类中申明一个成员变量LruCache ,而不能在getView()方法中申明。因为一个ListView所有的Item项只能维护这一个LruCache 。LruCache有一个构造方法LruCache(int maxSize) ,参数就是这个缓存空间最大的容量(多少字节)。申明一个LruCache对象一般需要复写它的sizeOf(K key, V value),用这个方法改变每个缓存条目计算大小的方式。Android源码中默认是返回1,说默认是以个数来计算的。(其实这里我也不太理解,有懂的朋友还望不吝赐教。)

 

Android sizeof()的源码:

/**
     * Returns the size of the entry for {@code key} and {@code value} in
     * user-defined units.  The default implementation returns 1 so that size
     * is the number of entries and max size is the maximum number of entries.
     *
     * <p>An entry's size must not change while it is in the cache.
     */
    protected int sizeOf(K key, V value) {
        return 1;
    }

不过我是参照官方文档写的。

private final int maxMemory = (int) Runtime.getRuntime().maxMemory();//获取当前应用程序所分配的最大内存
	private final int cacheSize = maxMemory / 5;//只分5分之一用来做图片缓存
	private LruCache<String, Bitmap> mLruCache = new LruCache<String, Bitmap>(
			cacheSize) {
		@Override
		protected int sizeOf(String key, Bitmap bitmap) {//复写sizeof()方法
			// replaced by getByteCount() in API 12
			return bitmap.getRowBytes() * bitmap.getHeight() / 1024; //这里是按多少KB来算
		}
	};

然后写一个异步加载图片的类AsyncImageLoader ; 这个类采用AsyncTask来异步加载图片。

package com.folyd.tuan.util;

import java.io.IOException;

import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;
import android.widget.ImageView;

import com.folyd.tuan.util.SimpleImageLoader;

/**
 * 图片异步加载类,有图片内存缓存
 * 
 * @author Folyd
 * 
 */
public class AsyncImageLoader extends AsyncTask<String, Void, Bitmap> {
	private ImageView image;
	private LruCache<String, Bitmap> lruCache;

	/**
	 * 构造方法,需要把ImageView控件和LruCache 对象传进来
	 * @param image 加载图片到此 {@code}ImageView
	 * @param lruCache 缓存图片的对象
	 */
	public AsyncImageLoader(ImageView image, LruCache<String, Bitmap> lruCache) {
		super();
		this.image = image;
		this.lruCache = lruCache;
	}

	@Override
	protected Bitmap doInBackground(String... params) {
		Bitmap bitmap = null;
		try {
			bitmap = SimpleImageLoader.getBitmap(params[0]);
		} catch (IOException e) {
			e.printStackTrace();
		}
		addBitmapToMemoryCache(params[0], bitmap);
		return bitmap;
	}

	@Override
	protected void onPostExecute(Bitmap bitmap) {
		image.setImageBitmap(bitmap);
	}
        //调用LruCache的put 方法将图片加入内存缓存中,要给这个图片一个key 方便下次从缓存中取出来
	private void addBitmapToMemoryCache(String key, Bitmap bitmap) {
		if (getBitmapFromMemoryCache(key) == null) {
			lruCache.put(key, bitmap);
		}
	}
        //调用Lrucache的get 方法从内存缓存中去图片
	public Bitmap getBitmapFromMemoryCache(String key) {
		return lruCache.get(key);
	}
}

  SimpleImageLoader 的getBitmap方法是一个简单的从网上获取图片的方法。

package com.folyd.tuan.util;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

/**
 * 简单的图片加载工具类,此类没有涉及到图片缓存。
 * @author Folyd
 *
 */
public class SimpleImageLoader {

	public static Bitmap getBitmap(String urlStr) throws IOException{
		Bitmap bitmap;
		URL url = new URL(urlStr);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setRequestMethod("GET");
		conn.setReadTimeout(5*1000);
		conn.setDoInput(true);
		conn.connect();
		InputStream is = conn.getInputStream();
		bitmap = BitmapFactory.decodeStream(is);
		is.close();
		return bitmap;
	}
}


然后在自定义的Adapter中封装一个加载图片的方法。这里涉及到AsyncTask 的一些知识,可以查看官方文档学习。

/**
	 * 
	 * @param urlStr 所需要加载的图片的url,以String形式传进来,可以把这个url作为缓存图片的key
	 * @param image ImageView 控件
	 */
	private void loadBitmap(String urlStr, ImageView image) {
		AsyncImageLoader asyncLoader = new AsyncImageLoader(image, mLruCache);//什么一个异步图片加载对象
		Bitmap bitmap = asyncLoader.getBitmapFromMemoryCache(urlStr);//首先从内存缓存中获取图片
		if (bitmap != null) {
			image.setImageBitmap(bitmap);//如果缓存中存在这张图片则直接设置给ImageView
		} else {
			image.setImageResource(R.drawable.thum);//否则先设置成默认的图片
			asyncLoader.execute(urlStr);//然后执行异步任务AsycnTask 去网上加载图片
		}
	}

然后在自定义Adapter的getView()方法方法中调用上面的loadBitmap()方法。


这样就实习了图片异步加载和内存缓存了。

看一下效果图:

                


当然没有磁盘缓存的ListView 绝对是不行的。ListView还有很多需要优化的技巧需要我们去不断学习。比如说图片懒加载。



知识共享-Android之ListView滑动加载、软缓存、懒加载(雷惊风) 本代码实例实现ListView滑动到底步快速加载,并加入缓存处理功能,仅供参考! 立即下载

相关推荐

ListView异步加载图片

①ListView异步加载图片的方式 ②给ImageView设置Tag,解决图片覆盖问题 ③采用LruCache缓存已经加载过的图片 ④当ListView滚动时不加载图片,滚动停止时才加载图片,从而达到ListView滑动很流畅的效果 ⑤当ListView加载图片时只加载当前屏幕内可见的条目

几分钟实现ListView加载图片数据的功能

ListView的简单使用前言一、ListView是什么?二、使用方法方法1:在布局文件中添加一个列表视图,并通过数组资源为其设置列表项。效果图:方法2:使用Adapter为ListView指定要显示的列表项。效果图: 前言 手机屏幕空间有限,能显示的内容不多。可以借助ListView来显示更多的内容。 ListView允许用户通过上下滑动来将屏幕外的数据滚动到屏幕内,同时屏幕内原有的数据滚动出屏幕,从而显示更多的数据内容。 一、ListView是什么? 一个数据控件,可以展示数据。 二、使用方法 方法

葫芦娃的博客 1018

Android开发之listview优化+图片异步加载缓存+避免图片显示闪烁

很多朋友在Android开发listview过程中都会碰到问题 比如从网上下载图片显示在界面 如果图片稍微大一点就会出现oom 或者显示的时候很容易出现图片闪烁等 这个项目能帮你解决

Android面试题避坑:ViewPager中的Framgent如何实现懒加载?_behavior_resume_only_current_fragment

/ 新引入的这个Op类型, 在这里会给这个Fragment设置允许的生命周期上限。// 滑走的会变成非主item, 设置其Lifecycle为STARTED。// 其他计算expected state的逻辑, 算出maxState。// 设置新滑到的主item的Lifecycle为RESUMED。// 初始化item时将其生命周期限制为STARTED。// mBehaviour为1的时候走新逻辑。// 如果应有的生命周期小于当前, 后退。// 与上面的switch类似。// 生命周期向前推进。

2401_84102979的博客 742

ListView优化及加载图片时内存溢出

ListView优化及加载图片时内存溢出

Androidstudio写的异步加载下载网络图片

自己写的androidstudio写的一个异步加载实现网络下载图片

android listview 懒加载,ListView之ViewStub的懒加载!

ViewStub 也是个View,但是懒加载,可以提前加入到 xml的布局文件中,但是不会加载,它的默认情况下是 View.GONE 当你把他设置成 View.Visable它会调用自己的inflate()方法* 这时候才 真正去构建自己,注意它的inflate()方法只能被调用一次!;所以为了提高性能,有个元素不需要一开始就加载可以考虑用 ViewStub,此外还有一个merg元素也是懒加载。老...

weixin_34138397的博客 417

信息系统项目管理师(高项)重点!

学习高项自己做的笔记

PanJWei的博客 3301

android listview 添加图片,Android添加图片到ListView或者RecyclerView显示

先上图点击+号就去选择图片实际上这个添加本身就是一个ListView或者 RecyclerView只是布局有些特殊itemxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/rootView"android:layout_width="wrap_content"android:layout_heigh...

weixin_42537450的博客 745

使用vcpkg快速安装opencascade并自动配置部署开发环境

广泛的开源库:vcpkg 提供了上千个流行的 C++ 开源库,用户可以通过简单的命令安装和集成这些库,包括 Boost、OpenCV、SQLite、fmt 等。确保包版本一致性:通过 vcpkg.json 文件,开发者可以指定依赖的库版本,确保项目在不同环境下的构建结果一致,避免由于依赖库版本不一致而导致的构建问题。强大的社区支持:Vcpkg 是开源项目,拥有活跃的社区和微软团队的支持,提供了稳定的更新和问题修复。快速更新:Vcpkg 社区活跃,库的更新速度较快,开发者可以迅速获得库的最新版本。

loujiand的博客 2293

从零构建知识图谱:本体工程与知识建模实战指南

本文是一份从零构建知识图谱的实战指南,重点阐述了知识建模与本体工程的核心地位。文章详细介绍了如何使用Protégé工具进行本体设计,包括定义领域、复用现有本体、构建类层次与属性约束,并讲解了如何利用D2RQ工具将关系数据库数据转换为RDF三元组,最终通过Apache Jena Fuseki搭建SPARQL端点进行知识查询与推理,让知识图谱真正“活”起来。

weixin_29057695的博客 571

android listview网络图片,Android ListView从网络获取图片及文字显示

上一篇文章说的是ListView展示本地的图片以及文本,这一篇说一下如何从网络获取图片以及文本来显示。事实上,一般是先获取Josn或sml数据,然后解释显示。我们先从网上获取xml,然后对其进行解析,最后显示在ListView上。具体步骤:客户端发出请求,获取xml客户端异步解析xmlListView将解析完的数据显示(1)xml布局文件mainxml,就是一个ListView。android:l...

weixin_39574246的博客 606

FPGA 上的 YOLOv8 实时目标检测:从模型优化到硬件加速全解析

本文全面解析了将YOLOv8目标检测模型部署到FPGA进行硬件加速的完整流程。通过模型裁剪、混合精度量化等优化手段,结合HLS设计专用计算引擎与数据流,实现了高能效比的实时推理。文章深入探讨了软硬协同部署、性能调试与优化技巧,为追求极致实时性与低功耗的边缘AI应用提供了从算法到硬件的实战指南。

weixin_29031161的博客 605

Android ListView 图片异步加载和图片内存缓存机制

转载至:http://blog.youkuaiyun.com/appte/article/details/10074395 点击打开链接 开发Android应用经常需要处理图片的加载问题。因为图片一般都是存放在服务器端,需要联网去加载,而这又是一个比较耗时的过程,所以Android中都是通过开启一个异步线程去加载。为了增加用户体验,给用户省流量,一般把加载完的图片先缓存下来,下次加载的时候就不需要再联网

yianemail的专栏 1037

天祥TX-1C单片机开发板-秒表程序

郭天祥TX-1C开发板实现秒表程序 附开发板图片和原理图 代码 #include <reg52.h> sbit key1=P3^4; //按键S2 sbit key2=P3^5; //按键S3 sbit U1=P2^6; //LED位选 sbit U2=P2^7; //LED片选 unsigned char code ledchar[]={ /...

Run_long_road 3513

基于Multisim/TINA的H桥电机驱动电路设计与仿真分析

摘要 本文基于Multisim/TINA仿真平台,对H桥电机驱动电路进行了系统设计与分析。研究重点包括H桥拓扑结构的工作原理、PWM调速控制方法以及两种驱动方案对比分析。通过光耦隔离驱动与IR2110专用驱动IC的仿真对比,验证了IR2110自举电路在高低侧驱动中的优势。仿真实验着重分析了死区时间对防止直通现象的关键作用,并建立了直流电机的R-L-E等效模型进行动态特性仿真。结果表明,采用IR2110驱动方案配合适当的栅极电阻和自举电容参数,能够实现电机的高效双向调速控制。本研究为实际电机驱动系统的设计提供

huanghm88的专栏 138

Android之ListView异步加载网络图片(优化缓存机制)和对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存

网上关于这个方面的文章也不少,基本的思路是线程+缓存来解决。下面提出一些优化: 1、采用线程池 2、内存缓存+文件缓存 3、内存缓存中网上很多是采用SoftReference来防止堆溢出,这儿严格限制只能使用最大JVM内存的1/4 4、对下载的图片进行按比例缩放,以减少内存的消耗 具体的代码里面说明。先放上内存缓存类的代码MemoryCache.java:

逍遥飞鹤的专栏 1444

别再用LabelImg了!我手搓了一个C#“一站式”YOLO工具箱,标注训练推理全搞定

这个工具箱目前已经在两个小型产线项目中试用,反馈非常好。效率提升:原本需要 2 天完成的“数据准备 - 训练 - 验证”循环,现在缩短到了 2 小时。门槛降低:产线技术员经过 10 分钟培训,就能独立完成新产品的模型迭代。当然,它还有改进空间未来计划集成主动学习功能:自动筛选出置信度低的图片,推荐优先标注。支持多模型管理:方便在不同产品型号间快速切换。增加PLC 通信模块:直接在推理界面配置 IO 信号,实现真正的软硬联动。最后想说工具的本质是服务于人。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 442

android ListView异步加载图片(双缓存)

首先声明,参考博客地址:http://www.iteye.com/topic/685986 对于ListView,相信很多人都很熟悉,因为确实太常见了,所以,做的用户体验更好,就成了我们的追求。。。 常见的ListView中很少全是文字的,一般都是图文共存的,而图片的来源是服务器端(很少有写在客户端的吧。。。考虑客户端的大小和更新的问题),所以,网络问题就成了图片是否能顺利加载

oneRain88的专栏 3万+

Calibre DRC

calibre DRC的运行方法,包括merge gds和加用dummy rule加dummy的方法

m0_61544122的博客 1万+

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

ListView异步加载图片--图片缓存和错位问题解决方案

问题1: 加载太多的图片很容易造成OOM异常。一、图片缓存方法1:使用二级缓存 ->自己维护一个缓存区 只要有足够的内存,就一直保持对象,直到发现内存吃紧且没有Strong Ref时才回收对象。 所以可以这么做:map里面的键是用来放图片地址的,既可以是网络上的图片地址,也可以SDcard上的图片地址, map里面的值里面放的是持有软引用的Bitmap.private Map<St

FlowLeaf 5112

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

上一篇: 2013金山西山居创意游戏程序挑战赛——复赛(1) 非诚勿扰
下一篇: 实现ListView A~Z快速索引
何必纠结于ID
博客等级 码龄14年 65粉丝 64原创
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值