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为我们妥善在后台管理好。

相关文章
|
消息中间件 存储 缓存
Android | App内存优化 之 内存泄漏 要点概述 以及 解决实战
Android | App内存优化 之 内存泄漏 要点概述 以及 解决实战
|
Java Linux Android开发
Android DVM和Java JVM以及ART概述
Android DVM(Dalvik Virtual Machine)和Java JVM(Java Virtual Machine)以及ART(Android RunTime)概述 JVM,Java Virtual Machine,Java虚拟机,JVM是基于栈的虚拟机,JVM栈是内存中连续的存储空间。
1503 0
|
4天前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
24 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
27天前
|
Java Android开发
Android 开发获取通知栏权限时会出现两个应用图标
Android 开发获取通知栏权限时会出现两个应用图标
14 0
|
1天前
|
数据库 Android开发 开发者
安卓应用开发:构建高效用户界面的策略
【4月更文挑战第24天】 在竞争激烈的移动应用市场中,一个流畅且响应迅速的用户界面(UI)是吸引和保留用户的关键。针对安卓平台,开发者面临着多样化的设备和系统版本,这增加了构建高效UI的复杂性。本文将深入分析安卓平台上构建高效用户界面的最佳实践,包括布局优化、资源管理和绘制性能的考量,旨在为开发者提供实用的技术指南,帮助他们创建更流畅的用户体验。