两款比较优秀的开源图片处理库框架:Universal-ImageLoader和Picasso。
简介:
Universal-ImageLoader是目前Android主流的图片处理库框架之一,作者是白俄罗斯的Sergey Tarasevich。
在Android图片处理中需要考虑的问题很多,例如OOM(内存溢出)、图片缓存和网络图片加载、多线程问题及图片压缩处理等等复杂的问题。但是Universal-ImageLoader已经帮我们把这些问题处理好了,对外提供了相应的完善的请求API,我们只需要按照要求使用即可。
特点:
缺点:
没有对本地文件压缩处理的相关API方法以及默认都是Src模式设置图片,没有针对Background属性开放API。
Universal-ImageLoader的用法:
1.Universal-ImageLoader的配置
可以全局配置:在Application里进行配置
可以针对单一加载图片的地方配置
例如:可配置图片缓存保存路径、线程池内加载的数量、缓存的文件数量 、每个缓存文件的最大长宽、加载过程中和加载失败时显示的图片等等。
2.用Universal-ImageLoader加载网络图片和本地图片
Universal-ImageLoader支持网络图片的加载和本地图片的加载,而且可以自动缓存、自动根据当前手机环境进行压缩处理防止出现OOM。
也可以监听整个图片的加载过程,可控。
代码:
MyApplication类:
package com.test.imageloader;
import java.io.File;
import android.app.Application;
import android.graphics.Bitmap;
import android.os.Environment;
import com.example.imageloaderandpicasso.R;
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;
/** * ImageLoader的全局配置 * @author Administrator * */
public class MyApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
this)
.memoryCacheExtraOptions(480, 800)
// max width, max height,即保存的每个缓存文件的最大长宽
.discCacheExtraOptions(480, 800, null)
// Can slow ImageLoader, use it carefully (Better don't use
// it)/设置缓存的详细信息,最好不要设置这个
.threadPoolSize(3)
// 线程池内加载的数量
.threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024))
// You can pass your own memory cache
// implementation/你可以通过自己的内存缓存实现
.memoryCacheSize(2 * 1024 * 1024)
.discCacheSize(50 * 1024 * 1024)
.discCacheFileNameGenerator(new Md5FileNameGenerator())
// 将保存的时候的URI名称用MD5 加密
.tasksProcessingOrder(QueueProcessingType.LIFO)
.discCacheFileCount(100)
// 缓存的文件数量
.discCache(
new UnlimitedDiscCache(new File(Environment
.getExternalStorageDirectory()
+ "/myApp/imgCache")))
// 自定义缓存路径
.defaultDisplayImageOptions(getDisplayOptions())
.imageDownloader(
new BaseImageDownloader(this, 5 * 1000, 30 * 1000))
.writeDebugLogs() // Remove for release app
.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;
}
}
MainActivity类:
package com.test.imageloader;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import com.example.imageloaderandpicasso.R;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
public class MainActivity extends Activity {
private ImageLoader loader;
private ImageView imageView;
// 网络图片uri
private String uri1 = "http://a.hiphotos.baidu.com/zhidao/pic/item/95eef01f3a292df58099afa6bd315c6034a8732e.jpg";
// 本地图片uri(格式:"file:///"+"本地路径")
private String uri2 = "file:///" + Environment.getExternalStorageDirectory()+"/DCIM/Camera/IMG20150502151010.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
loaderImage();
}
//加载图片的方法
private void loaderImage() {
loader = ImageLoader.getInstance();// 调用之前在MyApplication中的配置信息对ImageLoader进行实例化
// 将uri中的图片赋给图片控件ImageView
// loader.displayImage(uri1, imageView);
loader.displayImage(uri1, imageView, new ImageLoadingListener() {
@Override
//加载开始
public void onLoadingStarted(String arg0, View arg1) {
Log.i("tag", "onLoadingStarted");
}
@Override
//加载失败
public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
Log.i("tag", "onLoadingFailed");
}
@Override
//加载完成
public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {
Log.i("tag", "onLoadingComplete");
}
@Override
//加载取消
public void onLoadingCancelled(String arg0, View arg1) {
Log.i("tag", "onLoadingCancelled");
}
});
}
private void initView() {
imageView = (ImageView) findViewById(R.id.imageView);
}
}
简介:
Picasso是Square公司开源的一个Android图形缓存库。可以实现图片下载和缓存功能。
特点:
Picasso的用法:
1, Picasso的几个重要方法的介绍
图片异步加载:
Picasso.with(context).load(“http://baidu.com/logo.png“).into(imageView);
图片转换:转换图片以适应布局大小并减少内存占用
Picasso.with(context).load(url).resize(50, 50) .centerCrop() .into(imageView);
Adapter 中的下载:Adapter的重用会被自动检测到,Picasso会取消上次的加载
空白或者错误占位图片设置方法及本地资源文件的加载方法
2, 用Picasso加载网络图片和本地图片
Picasso采用链式调用加载和处理图片方式。
除了加载网络图片,picasso还支持加载Resources, assets, files, content providers中的本地资源文件。
代码:
package com.test.picasso;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;
import com.example.imageloaderandpicasso.R;
import com.squareup.picasso.Picasso;
public class PicassoTest extends Activity{
private ImageView imageView;
private String path = "http://auto.2500sz.com/auto/tpxw/hcsx/images/2011/8/27/94E17498DB894552AD046339C6FF611A.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_picasso);
initView();
//Picasso加载网络图片,并绑定ImageView控件
Picasso.with(this).load(path).into(imageView);
//对加载的图片进行图片的处理(设置加载后的图片的宽和高)
// Picasso.with(this).load(path).resize(100, 100).into(imageView);
//设置当加载出错时调用默认的图片
// Picasso.with(this).load(path).error(R.drawable.ic_launcher).into(imageView);
}
private void initView() {
imageView = (ImageView) findViewById(R.id.imageView);
}
}
运行结果截图:
总结:
一个简单的加载本地相册的图片的实例:
代码:(其中用到了两种方法加载本地相册的图片,1.使用android自带的SDK加载 2.获取到本地相册图片的路径后,通过ImageLoader加载图片)
package com.test.imageloader;
import java.io.FileNotFoundException;
import java.io.IOException;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import com.example.imageloaderandpicasso.R;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
public class MainActivity extends Activity {
private static final int CHOOSE_PICTURE = 111;
private static final int SCALE = 2;
private ImageLoader loader;
private ImageView imageView;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
setListener();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case CHOOSE_PICTURE:
// 照片的原始资源地址
Uri originalUri = data.getData();
// 方式一:
// openPhoto(originalUri);
// 方式二:
String path = getPhotoPath(originalUri);
String uri = "file:///" + path;
loaderImage(uri);
break;
default:
break;
}
}
}
// 打开相册的图片
private void openPhoto(Uri uri) {
try {
ContentResolver resolver = getContentResolver();
// 使用ContentProvider通过URI获取原始图片
Bitmap photo = MediaStore.Images.Media.getBitmap(resolver, uri);
if (photo != null) {
// 为防止原始图片过大导致内存溢出,这里先缩小原图显示,然后释放原始Bitmap占用的内存
Bitmap smallBitmap = zoomBitmap(photo,
photo.getWidth() / SCALE, photo.getHeight() / SCALE);
// 释放原始图片占用的内存,防止out of memory异常发生
photo.recycle();
imageView.setImageBitmap(smallBitmap);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// 获取在相册中选中的图片的路径
private String getPhotoPath(Uri uri) {
String[] proj = { MediaStore.Images.Media.DATA };
// 好像是android多媒体数据库的封装接口,具体的看Android文档
Cursor cursor = managedQuery(uri, proj, null, null, null);
// 按我个人理解 这个是获得用户选择的图片的索引值
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
// 将光标移至开头 ,这个很重要,不小心很容易引起越界
cursor.moveToFirst();
// 最后根据索引值获取图片路径
String path = cursor.getString(column_index);
return path;
}
private void initView() {
imageView = (ImageView) findViewById(R.id.imageView);
button = (Button) findViewById(R.id.button);
}
private void setListener() {
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent openAlbumIntent = new Intent(Intent.ACTION_GET_CONTENT);
openAlbumIntent.setType("image/*");
startActivityForResult(openAlbumIntent, CHOOSE_PICTURE);
}
});
}
// 加载图片的方法
private void loaderImage(String uri) {
loader = ImageLoader.getInstance();// 调用之前在MyApplication中的配置信息对ImageLoader进行实例化
// 将uri中的图片赋给图片控件ImageView
// loader.displayImage(uri1, imageView);
loader.displayImage(uri, imageView, new ImageLoadingListener() {
@Override
// 加载开始
public void onLoadingStarted(String arg0, View arg1) {
Log.i("tag", "onLoadingStarted");
}
@Override
// 加载失败
public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
Log.i("tag", "onLoadingFailed");
}
@Override
// 加载完成
public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {
Log.i("tag", "onLoadingComplete");
}
@Override
// 加载取消
public void onLoadingCancelled(String arg0, View arg1) {
Log.i("tag", "onLoadingCancelled");
}
});
}
/** 缩放Bitmap图片 **/
public Bitmap zoomBitmap(Bitmap bitmap, int width, int height) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix matrix = new Matrix();
float scaleWidth = ((float) width / w);
float scaleHeight = ((float) height / h);
matrix.postScale(scaleWidth, scaleHeight);// 利用矩阵进行缩放不会造成内存溢出
Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
return newbmp;
}
}
运行效果: