imageloader详解

最近在做相册管理的时候遇到了gridview中加在大量本地图片的情况,第一次只是很简单的用了gridview 没有添加任何的其他加速功能,因为加载的速度慢的真心可以。虽然功能是实现了,但是无法让人感到愉快。

百度了一下找到了imageloader这个开源框架,可以大大提升加载的速度因为本身其使用了异步加载的方法。

它基本可以做到一下几点:

  1. 多线程下载图片,图片可以来源于网络,文件系统,项目文件夹assets中以及drawable中等
  2. 支持随意的配置ImageLoader,例如线程池,图片下载器,内存缓存策略,硬盘缓存策略,图片显示选项以及其他的一些配置
  3. 支持图片的内存缓存,文件系统缓存或者SD卡缓存
  4. 支持图片下载过程的监听
  5. 根据控件(ImageView)的大小对Bitmap进行裁剪,减少Bitmap占用过多的内存
  6. 较好的控制图片的加载过程,例如暂停图片加载,重新开始加载图片,一般使用在ListView,GridView中,滑动过程中暂停加载图片,停止滑动的时候去加载图片
  7. 提供在较慢的网络下对图片进行加载

这个是在github上面的imageloader的项目https://github.com/nostra13/Android-Universal-Image-Loader。

接下来就是如何使用的问题:

1、如果是需要从网上下载图片的话,那么就需要设置权限了 首先要在androidmanifest中获得权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
这两句是分别是获得网络权限和SD卡的读写权限。

然后初始化imageloader需要自己写一个application来进行初始化
package com.example.administrator.first;

import android.app.Application;

import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;

/**
 * Created by Administrator on 2015/7/16.
 */
public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        ImageLoaderConfiguration configuration = ImageLoaderConfiguration
                .createDefault(this);
        ImageLoader.getInstance().init(configuration);
    }
}

这里我使用的是默认初始化的,如果自己需要设定的话可以自己选择。

File cacheDir = StorageUtils.getCacheDirectory(context);//获得缓存的默认地址
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
        .memoryCacheExtraOptions(480, 800) // 设置每个缓存文件的大小
        .diskCacheExtraOptions(480, 800, null)//设置每个硬盘缓存文件的大小
        .taskExecutor(...)
        .taskExecutorForCachedImages(...)
        .threadPoolSize(3) <span><span class="comment">// 线程池内加载的数量</span><span>  </span></span>
        .threadPriority(Thread.NORM_PRIORITY - 2) <span><span class="comment">// 线程优先级</span></span>
        .tasksProcessingOrder(QueueProcessingType.FIFO) // default
        .denyCacheImageMultipleSizesInMemory()
        .memoryCache(new LruMemoryCache(2 * 1024 * 1024))
        .memoryCacheSize(2 * 1024 * 1024)
        .memoryCacheSizePercentage(13) // default
        .diskCache(new UnlimitedDiscCache(cacheDir)) // 硬盘缓存的方法
        .diskCacheSize(50 * 1024 * 1024)//<span><span class="comment">硬盘缓存50MB</span><span></span></span>
        .diskCacheFileCount(100)<span><span></span><span class="comment">//缓存的File数量</span></span>
        .diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) <span><span></span><span class="comment">//将保存的时候的URI名称用HASHCODE加密</span><span> </span></span>
        .imageDownloader(new BaseImageDownloader(context)) // default
        .imageDecoder(new BaseImageDecoder()) // default
        .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
        .writeDebugLogs()
        .build();

因为默认的也差不多可以使用所以没怎么选,如果需要选择的话可以百度相应的选项的意思。
还需要在androidmanifest中在运行APP的时候先运行初始化的application。
<application android:name="MyApplication">假如这句话就会让这个先进行初始化。

然后是在你需要使用的使用初始化DisplayImageOptions对象

DisplayImageOptions options = new DisplayImageOptions.Builder()
        // 设置图片在下载期间显示的图片
                .showImageOnLoading(R.drawable.ic_stub)
                // 设置图片Uri为空或是错误的时候显示的图片
                .showImageForEmptyUri(R.drawable.ic_stub)
                // 设置图片加载/解码过程中错误时候显示的图片
                .showImageOnFail(R.drawable.ic_error)
                // 设置下载的图片是否缓存在内存中
                .cacheInMemory(false)
                // 设置下载的图片是否缓存在SD卡中
                .cacheOnDisc(true)
                // 保留Exif信息
                .considerExifParams(true)
                // 设置图片以如何的编码方式显示
                .imageScaleType(ImageScaleType.EXACTLY_STRETCHED)
                // 设置图片的解码类型
                .bitmapConfig(Bitmap.Config.RGB_565)
                // .decodingOptions(android.graphics.BitmapFactory.Options
                // decodingOptions)//设置图片的解码配置
                .considerExifParams(true)
                // 设置图片下载前的延迟
                .delayBeforeLoading(100)// int
                // delayInMillis为你设置的延迟时间
                // 设置图片加入缓存前,对bitmap进行设置
                // .preProcessor(BitmapProcessor preProcessor)
                .resetViewBeforeLoading(true)// 设置图片在下载前是否重置,复位
                // .displayer(new RoundedBitmapDisplayer(20))//是否设置为圆角,弧度为多少
                .displayer(new FadeInBitmapDisplayer(100))// 淡入
                .build();  

这是XML的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Gallery
        android:id="@+id/myGallery"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:spacing="3px" />

</LinearLayout>

.java代码

package com.example.administrator.text;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Gallery;
import android.widget.Toast;

import com.nostra13.universalimageloader.core.download.ImageDownloader;

import java.io.File;
import java.util.ArrayList;

public class MainActivity extends Activity {
    private Gallery myGallery;
    private ArrayList<String>array = null;
    private String []url;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))//查看当前的SD是不是存在
        {
            String path = Environment.getExternalStorageDirectory() + "/DCIM/Camera/";//获得照片的文件夹
            array = readlist(path);//获得照片的URL
            url = new String[array.size()];
            for(int i = 0;i < array.size();i++)
            {
                url[i] = ImageDownloader.Scheme.FILE.wrap(array.get(i));
            }
            myGallery = (Gallery) findViewById(R.id.myGallery);
            myGallery.setAdapter(new ImageGalleryAdapter(this,url));
            myGallery.setOnItemClickListener(new OnItemClickListenerImpl());
        }
        else
        {
            Toast.makeText(this,"无SD卡请插入",Toast.LENGTH_LONG);
        }
    }

    private class OnItemClickListenerImpl implements AdapterView.OnItemClickListener {//设置选择了其中的响应

        public void onItemClick(AdapterView<?> parent, View view, int position,
                                long id) {
            Toast.makeText(MainActivity.this, String.valueOf(position),
                    Toast.LENGTH_SHORT).show();
        }
    }

        @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private ArrayList<String> readlist(String path)//获得文件夹中的照片的URL
    {
        ArrayList<String> list = new ArrayList<String>();
        File file = new File(path);
        File []files = file.listFiles();
        if(files != null)
        {
            for(File f : files)
            {
                String filename = f.getName();
                if(filename.lastIndexOf(".") > 0 && filename.substring(filename.lastIndexOf(".")+1,filename.length()).equals("jpg"))
                {
                    list.add(f.getPath());
                }
            }
        }
        return list;
    }
}

适配器代码:

package com.example.administrator.text;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;

import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;

/**
 * Created by Administrator on 2015/7/17.
 */
public class ImageGalleryAdapter extends BaseAdapter {
    private Context context;
    private String []url;
    private DisplayImageOptions options;

    public ImageGalleryAdapter(Context context,String []s) {
        this.context = context;
        this.url = s;
        options = new DisplayImageOptions.Builder()//使用imageloader的方法进行初始化
                .showStubImage(R.drawable.ic_stub)
                .showImageForEmptyUri(null)
                .showImageOnFail(R.drawable.ic_error)
                .cacheInMemory()
                .cacheOnDisc()
                .build();
    }

    public int getCount() { // 取得要显示内容的数量
        return url.length;
    }

    public Object getItem(int position) { // 每个资源的位置
        return position;
    }

    public long getItemId(int position) { // 取得每个项的ID
        return position;
    }

    // 将资源设置到一个组件之中,很明显这个组件是ImageView
    public View getView(int position, View convertView, ViewGroup parent) {
        View view;
        view = convertView;
        ImageView imageView;
        if (convertView == null) {
            view = LayoutInflater.from(context).inflate(R.layout.item_list_image, null);
            imageView = (ImageView) view.findViewById(R.id.image);
            view.setTag(imageView);
        }
        else {
            imageView = (ImageView) view.getTag();
        }
        ImageLoader.getInstance().displayImage(url[position], imageView, options);
        ImageLoader.getInstance().displayImage(url[position],imageView);
        return view;
    }
}

item_list_imame.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <ImageView
        android:layout_width="80dip"
        android:layout_height="70dip"
        android:id="@+id/image"
        android:scaleType="centerCrop"
        android:adjustViewBounds="true"
        android:layout_marginLeft = "5dp"/>

</LinearLayout>

经过以上的测试,发现和正常的加载速度快了很多,如果不使用异步和这个框架的话,那么打开的开始就是白屏等好久才会出现,有了这个的话会慢慢的跳出来,如果存在了缓存
那么就是更加快。

最重要的是这样可以保证内存不会炸。因为如果同时加在所有的图片的话同时图片有几千张,内存直接炸。

如何还存在内存不够,我们则需要在初始化的时候进行一些调整 .threadPoolSize() // default  使用的线程数目减少

或者是在使用DisplayImageOptions的时候不添加缓存就可以

  1. .cacheInMemory(false) // default
  2. .cacheOnDisk(false) // default

或者是在DisplayImageOptions选项中配置bitmapConfig为Bitmap.Config.RGB_565,因为默认是ARGB_8888, 使用RGB_565会比使用ARGB_8888少消耗2倍的内存
这样就是初步的减少内存爆炸的可能性。

在内存缓存方面:

1. 只使用的是强引用缓存

  • LruMemoryCache(这个类就是这个开源框架默认的内存缓存类,缓存的是bitmap的强引用,下面我会从源码上面分析这个类)

2.使用强引用和弱引用相结合的缓存有

  • UsingFreqLimitedMemoryCache(如果缓存的图片总量超过限定值,先删除使用频率最小的bitmap)
  • LRULimitedMemoryCache(这个也是使用的lru算法,和LruMemoryCache不同的是,他缓存的是bitmap的弱引用)
  • FIFOLimitedMemoryCache(先进先出的缓存策略,当超过设定值,先删除最先加入缓存的bitmap)
  • LargestLimitedMemoryCache(当超过缓存限定值,先删除最大的bitmap对象)
  • LimitedAgeMemoryCache(当 bitmap加入缓存中的时间超过我们设定的值,将其删除)

3.只使用弱引用缓存

  • WeakMemoryCache(这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收掉)

我们可以在初始化的时候选择自己想用的

    ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(this)
            .memoryCache(new WeakMemoryCache())
            .build();  

<strong>在硬盘缓存方面:</strong><ul><li>FileCountLimitedDiscCache(可以设定缓存图片的个数,当超过设定值,删除掉最先加入到硬盘的文件)</li><li>LimitedAgeDiscCache(设定文件存活的最长时间,当超过这个值,就删除该文件)</li><li>TotalSizeLimitedDiscCache(设定缓存bitmap的最大值,当超过这个值,删除最先加入到硬盘的文件)</li><li>UnlimitedDiscCache(这个缓存类没有任何的限制)</li></ul><strong>
</strong>
 ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(this)
            .diskCache(new UnlimitedDiscCache(cacheDir))
            .build();

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

时间: 2024-11-29 01:42:14

imageloader详解的相关文章

Android开源框架Image-Loader详解

如果说评价一下哪个图片开源库最被广泛使用的话,我想应该可以说是Universal-Image-Loader,在主流的应用中如 果你随便去反编译几个,基本都能看到他的身影,它就像个图片加载守护者,默默的守护着图片加载.相信很多人对 这个异步加载图片框架还不是很熟,再加上最近它更改优化了好几个地方,而网上的大部分资料还是以前的,于是花 了几天时间专门的研究了下开源框架Universal-Image-Loader(实际上是近期项目刚好用到,且仔细的考虑过各种情 况),希望对新手能有所帮助,也希望大神能

【Android】RecyclerView详解(一)

1.介绍 RecyclerView是比 ListView 更高级且更具灵活性的组件. 此组件是一个用于显示庞大数据集的容器,可通过保持有限数量的视图进行非常有效的滚动操作. 如果您有数据集合,其中的元素将因用户操作或网络事件而发生改变,请使用 RecyclerView 小组件. RecyclerView使用起来很方便因为它: 提供了一种插拔式的体验,高度的解耦,异常的灵活使用; 显示的样式更丰富包括水平,竖直,Grid,瀑布显示方式; 可以通过ItemDecoration自定义Item间的间隔;

Android第三方登录详解2

接着Android第三方登录详解1讲 1.找到友盟  文档中心 2.找到 3.将 UMSocialService mController = UMServiceFactory.getUMSocialService("com.umeng.login");       这句话放到对应activity 弄成全局即可 4QQ 登录 //参数1为当前Activity, 参数2为开发者在QQ互联申请的APP ID,参数3为开发者在QQ互联申请的APP kEY. UMQQSsoHandler qqS

Android开源框架Universal-Image-Loader详解

如果说评价一下哪个图片开源库最被广泛使用的话,我想应该可以说是Universal-Image-Loader,在主流的应用中如 果你随便去反编译几个,基本都能看到他的身影,它就像个图片加载守护者,默默的守护着图片加载.相信很多人对 这个异步加载图片框架还不是很熟,再加上最近它更改优化了好几个地方,而网上的大部分资料还是以前的,于是花 了几天时间专门的研究了下开源框架Universal-Image-Loader(实际上是近期项目刚好用到,且仔细的考虑过各种情 况),希望对新手能有所帮助,也希望大神能

【译】UNIVERSAL IMAGE LOADER. PART 3(四个DisplayImage重载方法详解)

在之前的文章,我们重点讲了Android-Universal-Image-Loader的三个主要组件,现在我们终于可以开始使用它了. Android-Universal-Image-Loader有四个重载方法 void displayImage(String url, ImageView view) void displayImage(String url, ImageView view, DisplayImageOptions options) void displayImage(String

【译】UNIVERSAL IMAGE LOADER.PART 2---ImageLoaderConfiguration详解

ImageLoader类中包含了所有操作.他是一个单例,为了获取它的一个单一实例,你需要调用getInstance()方法.在使用ImageLoader来显示图片之前,你需要初始化它的配置-ImageLoaderConfiguration使用init(…)方法.然后,你就可以使用可以明确地根据需要使用不同形式的displayImage(…). 总之,ImageLoader最简单的用法如下所示(使用默认配置): ImageView imageView = ... // view, where th

Spring事务管理(详解+实例)

写这篇博客之前我首先读了<Spring in action>,之后在网上看了一些关于Spring事务管理的文章,感觉都没有讲全,这里就将书上的和网上关于事务的知识总结一下,参考的文章如下: Spring事务机制详解 Spring事务配置的五种方式 Spring中的事务管理实例详解 1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是要么都执行要么都

转载:DenseNet算法详解

原文连接:http://blog.csdn.net/u014380165/article/details/75142664 参考连接:http://blog.csdn.net/u012938704/article/details/53468483 本文这里仅当学习笔记使用,具体细节建议前往原文细度. 论文:Densely Connected Convolutional Networks 论文链接:https://arxiv.org/pdf/1608.06993.pdf 代码的github链接:h

MariaDB(MySQL)创建、删除、选择及数据类型使用详解

一.MariaDB简介(MySQL简介略过) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品.在存储引擎方面,使用XtraDB(英语:XtraDB)来代替MySQL的InnoDB. MariaDB由MySQL的创始人Michael Widenius(英语:Michael Widenius)主导开发,他早前曾以10亿美元的价格,将自己创建的公司MySQL A