Android网络图片加载缓存处理库的使用---第三方库学习笔记(五)

两款比较优秀的开源图片处理库框架:Universal-ImageLoader和Picasso。

Universal-ImageLoader

简介:
Universal-ImageLoader是目前Android主流的图片处理库框架之一,作者是白俄罗斯的Sergey Tarasevich。
在Android图片处理中需要考虑的问题很多,例如OOM(内存溢出)、图片缓存和网络图片加载、多线程问题及图片压缩处理等等复杂的问题。但是Universal-ImageLoader已经帮我们把这些问题处理好了,对外提供了相应的完善的请求API,我们只需要按照要求使用即可。

特点:

  1. 支持本地图片和网络图片的多线程异步加载和缓存处理
  2. 个性化的配置自己项目的ImageLoader
  3. 图片加载过程的监听回调
  4. 自动对加载的图片针对当前剩余内存进行裁剪优化,防止OOM
  5. 较好的控制图片的加载过程,例如暂停图片加载,重新开始加载图片

缺点:
没有对本地文件压缩处理的相关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);
    }
}

运行结果:
Android网络图片加载缓存处理库的使用---第三方库学习笔记(五)_第1张图片

Picasso

简介:
Picasso是Square公司开源的一个Android图形缓存库。可以实现图片下载和缓存功能。

特点:

  1. 加载载网络或本地图片并自动缓存处理
  2. 链式调用
  3. 图形转换操作,如变换大小,旋转等,提供了接口来让用户可以自定义转换操作
  4. 在Adapter中回收和取消当前的下载功能

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);
    }

}

运行结果截图:
Android网络图片加载缓存处理库的使用---第三方库学习笔记(五)_第2张图片

总结:

  1. 都有高效的网络图片下载和缓存性能
  2. Universal-ImageLoader功能多,灵活使用配置
  3. Picasso使用复杂的图片压缩转换来尽可能的减少内存消耗
  4. 在Adapter中需要取消已经不在视野范围的ImageView图片资源的加载,否则会导致图片错位,Picasso已经解决了这个问题。

一个简单的加载本地相册的图片的实例:
代码:(其中用到了两种方法加载本地相册的图片,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;
    }
}

运行效果:
Android网络图片加载缓存处理库的使用---第三方库学习笔记(五)_第3张图片

版权声明:本文为博主原创文章,未经博主允许不得转载。

你可能感兴趣的:(Android网络图片加载缓存处理库的使用---第三方库学习笔记(五))