Android ImageLoader(Android-Universal-Image-Loader)【1】概述及使用简介

简介: Android ImageLoader(Android-Universal-Image-Loader)【1】概述及使用简介一,前言:为什么要引入Android-Universal-Image-Loader?众...


Android ImageLoader(Android-Universal-Image-Loader)【1】概述及使用简介


一,前言:为什么要引入Android-Universal-Image-Loader?

众所周知,简单的几个ImageView加载几个图像资源、或者这几个图像资源是从本地加载时无需考虑过多直接加载即可,但当成千上百个ImageView加载成千上百个图像、尤其是当这些图片还是从网络中异步获取,那么需要考虑的问题细节很多很繁琐且容易出错,现在随便举例其中几条:


(1)最基本的问题,网络不可靠,可能在不可靠网络加载过程中,图片加载发生难以预估的失败。


(2)已经从网络或本地中加载成功的图片,应该避免重复加载,重复加载造成网络流量浪费,以及设备计算资源的重复浪费,因此需要考虑图片缓存策略。缓存分为两级缓存:第一级:内存缓存,第二级:“硬盘”缓存(通常是手机的外置存储如SD卡和内置存储)。实现这样的层级缓存策略需要自己维护和组织。内存缓存可以考虑使用Android的LruCache,详情参考我的另外两篇文章:
a、《使用新式LruCache取代SoftReference缓存图片,Android异步加载图片》,文章链接地址:http://blog.csdn.net/zhangphil/article/details/43667415
b、或者自己按照LruCache设计思路实现和管理内存管理,《基于Java LinkedList,实现Android大数据缓存策略》,文章链接地址:http://blog.csdn.net/zhangphil/article/details/44116885
硬盘缓存则要自己建立缓存索引和缓存文件结构(如何建立缓存目录?内存在何时机把硬盘缓存的图片加入等等问题)。


(3)设想这一种情况,在一个Android竖直方向上ListView中有成千上万条图片item,每条item中的图片均需从网络获取。用户手指在屏幕上快速滑动,滑动过程中,极有可能可见视野内的图片还没有加载完成后,用户已经快速的往下滑看下面的图片去了。而上面已经消失的图片加载线程如果置之不理任由其运作,那么,当用户在不断的下拉和上拉过程中,将会造成线程不断的重建和运行,内存开销极大。而对于用户来来,最紧迫的当前可见视野的图片加载显示可能因为线程过多而被无限期拖延到最后显示。这种情况一般得应对策略师自己维护和管理一个线程池(关于Java线程池,详情请参考我的另外一篇文章:《Java线程池:ExecutorService,Executors》,文章链接地址:http://blog.csdn.net/zhangphil/article/details/43898637 ),自己管理和维护多线程下载任务队列,显然,需要考虑的线程队列问题很多,很繁琐。

等等还有很多未列举出来的细节问题。

为了避免重复造轮子,这种情况下最好考虑使用一些业界比较成熟稳定的开源框架。
Android ImageLoader(Android-Universal-Image-Loader),是github上的一个第三方开源图像加载库。该项目在github上的链接地址:
https://github.com/nostra13/Android-Universal-Image-Loader 
Android-Universal-Image-Loader主要应用领域是ImageView加载图片。该开源框架对上述问题给予了充分的解决。并提供了其他额外的附加功能(如加载的图片尺寸,加载动画等等)。


二、Android-Universal-Image-Loader使用简介。

首先到Android-Universal-Image-Loader官方网址下载项目包,使用可以分为两种方法
(1)把Android-Universal-Image-Loader的全部实现源代码(*.java)放入到自己的项目目录src下,当作是自己的源代码使用。
(2)导入Android-Universal-Image-Loader的jar库文件,比如universal-image-loader-1.9.4.jar。
两种方式都可以,看个人偏好。

我用的是第一种方法,这样可以方便查阅甚至直接二次定制修改Android-Universal-Image-Loader的源代码为自己所用。
代码结构层次如图:


然后就可以直接使用,现给出一个示例。
测试用的MainActivity.java:

package zhangphil.imageloader;

import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;

import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;

public class MainActivity extends ListActivity {

	private ImageLoader mImageLoader = null;

	// 加载的图片资源URL
	private final String ZHANGPHIL_CSDN_LOGO_URL = "http://avatar.csdn.net/9/7/A/1_zhangphil.jpg";

	// 加载的数目,假定数据总量很大
	private final int ITEM_COUNT = 10000;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		ListView lv = this.getListView();
		ArrayAdapter adapter = new MyArrayAdapter(this, -1);
		lv.setAdapter(adapter);

		mImageLoader = ImageLoader.getInstance();
		mImageLoader.init(getImageLoaderConfiguration());
	}

	private ImageLoaderConfiguration getImageLoaderConfiguration() {

		ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
				this)
				.threadPoolSize(3)
				// 线程数量
				.threadPriority(Thread.NORM_PRIORITY)
				// 线程优先级
				.tasksProcessingOrder(QueueProcessingType.FIFO)
				.denyCacheImageMultipleSizesInMemory()
				.memoryCacheSize(1024 * 1024 * 10) // 内存缓存的容量10MB
				.diskCacheFileCount(100)// 缓存的文件数量
				.diskCacheSize(1024 * 1014 * 100)// 硬盘缓存的大小100MB
				.writeDebugLogs()// 输出日志
				.build();

		return config;
	}

	private DisplayImageOptions getDisplayImageOptions() {

		DisplayImageOptions options = new DisplayImageOptions.Builder()
				.showImageOnLoading(R.drawable.loading)
				// 加载过程中显示的图片
				.showImageForEmptyUri(R.drawable.ic_launcher)
				// 空URI显示的图片
				.showImageOnFail(R.drawable.error)
				// 加载失败时候显示内容
				.cacheInMemory(true)
				// 缓存到内存
				.cacheOnDisk(true)
				// 缓存到硬盘
				.considerExifParams(true)
				.displayer(new FadeInBitmapDisplayer(1000))// 淡入加载图片显示
				.build();

		return options;
	}

	private class MyArrayAdapter extends ArrayAdapter {

		private LayoutInflater inflater;
		private int resId = R.layout.item;
		private DisplayImageOptions mDisplayImageOptions;

		public MyArrayAdapter(Context context, int resource) {
			super(context, resource);
			inflater = LayoutInflater.from(getContext());
			mDisplayImageOptions = getDisplayImageOptions();
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			if (convertView == null)
				convertView = inflater.inflate(resId, null);

			ImageView imageView = (ImageView) convertView
					.findViewById(R.id.image);
			mImageLoader.displayImage(ZHANGPHIL_CSDN_LOGO_URL, imageView,
					mDisplayImageOptions);

			return convertView;
		}

		@Override
		public int getCount() {
			return ITEM_COUNT;
		}
	}
	
	
	// private File getMyCacheDir() {
	// File sdRoot = Environment.getExternalStorageDirectory();
	// String myImageLoaderCacheFileDir = "ImageLodaerCache";
	// File cacheFileDir = new File(sdRoot, myImageLoaderCacheFileDir);
	// return cacheFileDir;
	// }
}


Item.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/image" >
    
</ImageView>

素材error.png和Loading.gif可以根据个人的需要选取不同的图片资源。


ImageLoader在使用之前需要做一些初始化工作,配置ImageLoaderConfiguration和DisplayImageOptions 。然后就可以直接使用ImageLoader的displayImage()方法从网络或本地存储中异步加载图片资源。而关于图片资源的缓存和异步下载线程池队列则交由ImageLoader为我们妥善在后台管理好。

相关文章
|
6月前
|
缓存 算法 Java
Linux内核新特性年终大盘点-安卓杀后台现象减少的背后功臣MGLRU算法简介
MGLRU是一种新型内存管理算法,它的出现是为了弥补传统LRU(Least Recently Used)和LFU(Least Frequently Used)算法在缓存替换选择上的不足,LRU和LFU的共同缺点就是在做内存页面替换时,只考虑内存页面在最近一段时间内被访问的次数和最后一次的访问时间,但是一个页面的最近访问次数少或者最近一次的访问时间较早,可能仅仅是因为这个内存页面新近才被创建,属于刚刚完成初始化的年代代页面,它的频繁访问往往会出现在初始化之后的一段时间里,那么这时候就把这种年轻代的页面迁移出去
|
6月前
|
存储 编解码 API
Android Media Framework(一)OpenMAX 框架简介
OpenMAX IL是Khronos Group为嵌入式和移动设备设计的低层级接口,用于统一调用音频、视频和图像编解码器,确保跨平台兼容性。它包括Core API(管理组件加载和方法调用)和Component API(组件实现,如源、接收器、编解码器等)。组件通过端口进行数据交互,客户端使用Core API加载和控制组件。Android引入OMX IL以支持不同芯片上的编解码器。组件状态包括Loaded、Idle、Executing和Invalid。组件架构涉及参数配置、命令处理和缓冲区管理,数据交换通过回调函数完成,端口持有预分配或组件自分配的缓冲区。
|
SQL 人工智能 Java
Android 命令行工具简介
Android SDK 中包含了开发应用所需的多个软件包。本页列出了可供使用的最重要的命令行工具(按提供这些工具的软件包整理)。
|
SQL 人工智能 移动开发
Android etc1tool之png图片转换pkm 和 zipalign简介
etc1tool 是一种命令行实用程序,可用于将 PNG 图片编码为 ETC1 压缩标准格式(PKM),并将 ETC1 压缩图片解码回 PNG。
|
Java Linux API
#1,Android 体系结构 2000字简介 入门Android(Studio)开发
#1,Android 体系结构 2000字简介 入门Android(Studio)开发
|
11月前
|
Java 测试技术 持续交付
百度搜索:蓝易云【NetMock简介:简化 Java,Android和Kotlin多平台中的HTTP请求测试?】
使用NetMock,您可以在单元测试、集成测试和端到端测试中轻松地模拟和验证HTTP请求和响应,而无需实际发送请求到外部服务。这样可以提高测试的可靠性和可控性,并加快测试执行的速度。无论是在开发过程中还是在持续集成环境中,NetMock都可以帮助您更轻松地进行HTTP请求测试,提高代码质量和稳定性。
64 1
|
6月前
|
Linux 网络安全 开发工具
Android APP入门之Android的简介以及Android Studio开发环境的搭建和测试(2022最新 图文解释 简单易懂)
Android APP入门之Android的简介以及Android Studio开发环境的搭建和测试(2022最新 图文解释 简单易懂)
157 0
|
XML Java 开发工具
Android apkanalyzer简介
Android apkanalyzer简介
|
XML Java 编译器
[Android JNI] --- Java和Android简介
[Android JNI] --- Java和Android简介
109 1
|
监控 安全 Java
【Android 逆向】加壳技术简介 ( 动态加载 | 第一代加壳技术 - DEX 整体加固 | 第二代加壳技术 - 函数抽取 | 第三代加壳技术 - VMP / Dex2C | 动态库加壳技术 )
【Android 逆向】加壳技术简介 ( 动态加载 | 第一代加壳技术 - DEX 整体加固 | 第二代加壳技术 - 函数抽取 | 第三代加壳技术 - VMP / Dex2C | 动态库加壳技术 )
656 1