Android之Universal Image Loader

背景:

Android中图片处理存在的难点:

1.OOM内存溢出;

2.图片尺寸和缩略图处理的平衡;

3.网络图片的加载与缓存机制;


简介:

Universal-ImageLoader是目前Android主流的图片处理库框架之一,作者是白俄罗斯的Sergey Tarasevich。

在Android图片处理中需要考虑的问题很多,例如OOM、图片缓存和网络图片加载、多线程问题及图片压缩处理等等复杂的问题。但是Universal-ImageLoader已经帮我们把这些问题处理好了,对外提供了相应的完善的请求API,我们只需要按照要求使用即可。


特点:

1.支持本地图片和网络图片的多线程异步加载和缓存处理;

2.个性化的配置自己项目的ImageLoader;

3.图片加载过程的监听回调;

4.自动对加载的图片针对当前剩余内存进行裁剪优化,防止OOM;

5.较好的控制图片的加载过程,例如暂停图片加载,重新开始加载图片;


缺点:

没有对本地文件压缩处理的相关API方法以及默认都是Src模式设置图片,没有针对Background属性开放API。


用法:

1.Universal-ImageLoader的配置:

可以全局配置:在Application里进行配置。
可以针对单一加载图片的地方配置。

例如:可配置图片缓存保存路径、线程池内加载的数量、缓存的文件数量 、每个缓存文件的最大长宽、加载过程中和加载失败时显示的图片等等。


2.用Universal-ImageLoader加载网络图片和本地图片:

Universal-ImageLoader支持网络图片的加载和本地图片的加载,而且可以自动缓存、自动根据当前手机环境进行压缩处理防止出现OOM。

也可以监听整个图片的加载过程,可控。


下面实现一个ListView显示网络图片:


首先需要在工程中加入Universal-ImageLoader的jar包,然后在Manifest中加入读取sd卡的权限和访问网络的权限

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>


然后在MyApplication中配置Universal-ImageLoader

import java.io.File;

import android.app.Application;
import android.graphics.Bitmap;
import android.os.Environment;

import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.UsingFreqLimitedMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;

public class MyApplication extends Application {

	@Override
	public void onCreate() {
		super.onCreate();

		ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
				MyApplication.this)
				// max width, max height,即保存的每个缓存文件的最大宽高
				.memoryCacheExtraOptions(100, 100)
				// 线程池内加载的数量
				.threadPoolSize(3)
				.threadPriority(Thread.NORM_PRIORITY - 1)
				.memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024))
				.memoryCacheSize(2 * 1024 * 1024)
				.diskCacheSize(50 * 1024 * 1024)
				// 将保存的时候的URI名称用MD5 加密
				.diskCacheFileNameGenerator(new Md5FileNameGenerator())
				.diskCacheFileCount(100)
				// 自定义缓存路径
				.diskCache(
						new UnlimitedDiscCache(new File(Environment
								.getExternalStorageDirectory()
								+ "")))
				.denyCacheImageMultipleSizesInMemory()
				.tasksProcessingOrder(QueueProcessingType.FIFO)
				.defaultDisplayImageOptions(getDisplayOptions())
				.imageDownloader(new BaseImageDownloader(this, 5*1000, 30*1000))
				//.writeDebugLogs()
				.build(); //开始构建
		
		ImageLoader.getInstance().init(config);
	}
	
	private DisplayImageOptions getDisplayOptions() {
		DisplayImageOptions options;
		options = new DisplayImageOptions.Builder()
				.showImageOnLoading(R.drawable.ic_launcher) // 设置图片在下载期间显示的图片
				.showImageForEmptyUri(R.drawable.ic_launcher)// 设置图片Uri为空或是错误的时候显示的图片
				.showImageOnFail(R.drawable.ic_launcher) // 设置图片加载/解码过程中错误时候显示的图片
				.cacheInMemory(true)// 设置下载的图片是否缓存在内存中
				.cacheOnDisc(true)// 设置下载的图片是否缓存在SD卡中
				.considerExifParams(true) // 是否考虑JPEG图像EXIF参数(旋转,翻转)
				.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)// 设置图片以如何的编码方式显示
				.bitmapConfig(Bitmap.Config.RGB_565)// 设置图片的解码类型//
				// .delayBeforeLoading(int delayInMillis)//int
				// delayInMillis为你设置的下载前的延迟时间
				// 设置图片加入缓存前,对bitmap进行设置
				// .preProcessor(BitmapProcessor preProcessor)
				.resetViewBeforeLoading(true)// 设置图片在下载前是否重置,复位
				.displayer(new RoundedBitmapDisplayer(20))// 是否设置为圆角,弧度为多少
				.displayer(new FadeInBitmapDisplayer(100))// 是否图片加载好后渐入的动画时间
				.build();// 构建完成
		return options;
	}

}

这里找了四张网络菜谱图片,在代码中新添加一个菜类:

//表示菜类(经过烹调的蔬菜、蛋品、肉类等)
public class Dish {

	private String imgUrl; // 图片地址
	private String name; // 菜名
	private String price; // 菜价
	
	public Dish(String imgUrl, String name, String price) {
		this.imgUrl = imgUrl;
		this.name = name;
		this.price = price;
	}

	public String getImgUrl() {
		return imgUrl;
	}

	public void setImgUrl(String imgUrl) {
		this.imgUrl = imgUrl;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPrice() {
		return price;
	}

	public void setPrice(String price) {
		this.price = price;
	}

}


主界面类中,首先获取到ImageLoad对象,然后调用该对象的displayImage方法加载网络图片

import java.util.ArrayList;

import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends Activity {

	/**
	 * 如果需要读取本地图片,可以使用
	 * String uri = "file:///" + "本地路径";
	 */
	
	private ImageLoader mImageLoader;
	
	private static final String BASE_URL = "http://img1.3lian.com/img2011/w1/106/85/";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		//获取到ImageLoader对象
		mImageLoader = ImageLoader.getInstance();
		
		ArrayList<Dish> dishList = new ArrayList<Dish>();
		
		dishList.add(new Dish(BASE_URL+"42.jpg", "水煮鱼片", "38.00"));
		dishList.add(new Dish(BASE_URL+"34.jpg", "小炒肉", "18.00"));
		dishList.add(new Dish(BASE_URL+"37.jpg", "清炒时蔬", "15.00"));
		dishList.add(new Dish(BASE_URL+"11.jpg", "金牌烤鸭", "36.00"));
		dishList.add(new Dish(BASE_URL+"12.jpg", "粉丝肉煲", "20.00"));
		
		ListView mListView = (ListView) this.findViewById(R.id.listview);
		MainListViewAdapter adapter = new MainListViewAdapter(dishList);
		mListView.setAdapter(adapter);
	}

	//网络图片加载监听器对象
	private ImageLoadingListener mImageLoadingListener = new ImageLoadingListener() {

		@Override
		public void onLoadingStarted(String arg0, View arg1) {
			System.out.println("onLoadingStarted...");
		}

		@Override
		public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
			System.out.println("onLoadingFailed...");
		}

		@Override
		public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {
			System.out.println("onLoadingComplete...");
		}

		@Override
		public void onLoadingCancelled(String arg0, View arg1) {
			System.out.println("onLoadingCancelled...");
		}
	};

	//ListView适配器
	private class MainListViewAdapter extends BaseAdapter {

		private ArrayList<Dish> dishList;

		public MainListViewAdapter(ArrayList<Dish> list) {
			this.dishList = list;
		}

		@Override
		public int getCount() {
			return dishList.size();
		}

		@Override
		public Object getItem(int position) {
			return dishList.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ListViewItemHolder item = null;
			if (convertView == null) {
				convertView = LayoutInflater.from(MainActivity.this).inflate(
						R.layout.main_listview_item, null);
				item = new ListViewItemHolder();
				item.img_iv = (ImageView) convertView
						.findViewById(R.id.imageView1);
				item.name_textview = (TextView) convertView
						.findViewById(R.id.textView1);
				item.price_textview = (TextView) convertView
						.findViewById(R.id.textView2);

				convertView.setTag(item);
			} else {
				item = (ListViewItemHolder) convertView.getTag();
			}

			Dish dish = dishList.get(position);
			
			//这里就是加载网络图片,加载的整个过程都会有调用监听器中的回调方法
			mImageLoader.displayImage(dish.getImgUrl(), item.img_iv,
					mImageLoadingListener);
			
			item.name_textview.setText(dish.getName());
			item.price_textview.setText(dish.getPrice()+"元");

			return convertView;
		}

	}

	//ListView的Item组件类
	private class ListViewItemHolder {
		ImageView img_iv;
		TextView name_textview;
		TextView price_textview;
	}
}


下面是整个工程的下载链接,有兴趣的可以下载导入到自己的Eclipse中去运行:

Android Universal ImageLoader


你可能感兴趣的:(android,Universal,imageloade)