关于ImageLoader的一些东西

  网络图片异步加载 其实有关图片加载存在这样一个问题,图片的下载始终是一个耗时的操作,这个时候如果把图片加载放在主线程中话的是不明智的,模拟一个这样的场景, 假如在一个listview或RecyclerView中,每一个listitem中都有一张网络图片,假如不使用网络异步处理的话,滑动工作会特别卡,因为必须加载网图片后 ,才会加载下个item。除了这些,网络图片加载还存在很多优化,下面是ImageLoader对于网络图片加载的优化内容:

  • 加载过程使用异步,这里使用AsyncTask
  • 加载图片后,将图片放入缓存,不必每次都从网络上请求,节省流量,加快加载速度
  • 使用ViewHolder,这点就不必多说了
  • 监听滑动过程,其实我们知道的,在滑动的时候其实我们是没有必要加载图片的,等滑动结束的时候,加载当前页面的图片

  其实网上有很多类似的开源框架,但是为了理解其中原理,我自己写了一个ImageLoader。同时在加载过程中我自己写了一个ProgressDialog,显示效果如下

  1、关于异步加载:

  我的Demo里面使用的异步加载方法是AsyncTask,AsyncTask是一个很创建的异步方式,这里就不做太多介绍,只要在doInBackground方法中添加图片的网络加载即可,以下是代码:

private class NewSAsyncTask extends AsyncTask<String, Void, Bitmap> {
		private ImageView mimageView;
		private String mUrl;
		private int mType;

		public NewSAsyncTask(ImageView imageview, String url,int type) {
			mimageView = imageview;
			mUrl = url;
			mType=type;

		}

		@Override
		protected Bitmap doInBackground(String... params) {
			String url=params[0];
			Bitmap bitmap=getBitmapFromUrl(mUrl,mType);
			if(bitmap!=null){
				addBitmapToCache(url, bitmap);
			}
			return bitmap;
		}

		@Override
		protected void onPostExecute(Bitmap bitmap) {
			super.onPostExecute(bitmap);
			if (mimageView.getTag().equals(mUrl)) {
				mimageView.setImageBitmap(bitmap);
			}

		}

	}

  2、加载的图片放入缓存,或从缓存中读取图片--LruCache

  LruCache是android提供给我的一个有关于手机缓存中插入和读取数据的类,使用起来也很方便,以下是代码:

public ImageLoaderUtil() {
		int maxMemory = (int) Runtime.getRuntime().maxMemory();
		int cacheSize = maxMemory / 8;
		mcache = new LruCache<String, Bitmap>(cacheSize) {
			@SuppressLint("NewApi")
			@Override
			protected int sizeOf(String key, Bitmap value) {
				return value.getByteCount();
			}
		};
	}

	public void addBitmapToCache(String url, Bitmap bitmap) {
		if (getBitmapFromCache(url) == null) {
			mcache.put(url, bitmap);
		}
	}

	public Bitmap getBitmapFromCache(String url) {
		return mcache.get(url);

	}

  上面的代码中先是获取当前手机可用的最大内容,然后取其8分之一,用于我们使用的缓存。

  3、判断手指滑动状态

  这个很简单,直接使用ListView或RecyclerView的滑动监听即可。当手指停止滑动的时候,判断当前屏幕中都显示哪些item,然后在加载这些item。这样一来,在手指滑动的过程中,不进行任何有关加载的相关操作,节省了流量,加快了加载速度,同时提升了用户体验。

  4、ImageLoader的逻辑顺序

  首先判断在LruCache中通过url判断是否有欲加载的图片,没有的话从网络上加载,并使用url和图片的键值对放入LruCache中。同时监听手机滑动,当收停止滑动的时候在进行加载,滑动过程中不进行任何加载。

  下面是ImageLoader的完整代码:

package xml.org.today.util;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;
import android.widget.ImageView;

public class ImageLoaderUtil {
    private LruCache<String, Bitmap> mcache;

    public ImageLoaderUtil() {
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        int cacheSize = maxMemory / 8;
        mcache = new LruCache<String, Bitmap>(cacheSize) {
            @SuppressLint("NewApi")
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getByteCount();
            }
        };
    }

    public void addBitmapToCache(String url, Bitmap bitmap) {
        if (getBitmapFromCache(url) == null) {
            mcache.put(url, bitmap);
        }
    }

    public Bitmap getBitmapFromCache(String url) {
        return mcache.get(url);

    }

    /**
     * 异步加载网络图片
     *
     * @param imageview
     * @param url
     * @param type      1、圆角图片
     */
    public void getImageByAsyncTask(ImageView imageview, String url, int type) {
        Bitmap bitmap = getBitmapFromCache(url);
        if (bitmap == null) {
            new NewSAsyncTask(imageview, url, type).execute(url);
        } else {
            imageview.setImageBitmap(bitmap);
        }

    }

    private class NewSAsyncTask extends AsyncTask<String, Void, Bitmap> {
        private ImageView mimageView;
        private String mUrl;
        private int mType;

        public NewSAsyncTask(ImageView imageview, String url, int type) {
            mimageView = imageview;
            mUrl = url;
            mType = type;

        }

        @Override
        protected Bitmap doInBackground(String... params) {
            String url = params[0];
            Bitmap bitmap = getBitmapFromUrl(mUrl, mType);
            if (bitmap != null) {
                addBitmapToCache(url, bitmap);
            }
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            if (mimageView.getTag().equals(mUrl)) {
                mimageView.setImageBitmap(bitmap);
            }

        }

    }

    public Bitmap getBitmapFromUrl(String urlString, int type) {
        Bitmap bitmap;
        Bitmap outbitmap;
        InputStream is = null;
        try {
            URL url = new URL(urlString);
            try {
                HttpURLConnection connection = (HttpURLConnection) url
                        .openConnection();
                is = new BufferedInputStream(connection.getInputStream());
                bitmap = BitmapFactory.decodeStream(is);
                if (type == 1) {
                    outbitmap = toRoundBitmap(bitmap);
                } else {
                    outbitmap = bitmap;
                }

                connection.disconnect();
                return outbitmap;
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static Bitmap toRoundBitmap(Bitmap bitmap) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        Paint paint = new Paint();
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        Rect rect;
        if (width >= height) {
            rect = new Rect((width - height) / 2, 0, (width - height) / 2
                    + height, height);
        } else {
            rect = new Rect(0, (height - width) / 2, width, width
                    + (height - width) / 2);
        }
        RectF rectF = new RectF(rect);
        canvas.drawOval(rectF, paint);
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rectF, paint);
        return output;
    }
}

  调用的方式也很简单:

ImageLoaderUtil mImageLoaderUtil=new ImageLoaderUtil();
mImageLoaderUtil.getImageByAsyncTask(mView,mUrl,1);

  上面的代码中mView是欲加载图片的ImageView,mUrl是图片的远程地址,1代表欲加载圆角图片。

  上面代码的github地址是:https://github.com/jiushi555/ImageLoaderDemo。

时间: 2024-11-13 18:48:43

关于ImageLoader的一些东西的相关文章

android使用ImageLoader实现图片缓存(安卓开发必备)

相信大家在学习以及实际开发中基本都会与网络数据打交道,而这其中一个非常影响用户体验的就是图片的缓存了,若是没有弄好图片缓存,用户体验会大大下降,总会出现卡顿情况,而这个问题尤其容易出现在ListView中的Item有图片的情况中. 前面与大家分享了一个网络连接框架Retrofit,里面也有类似的图片加载的picasso,大家都可以去体验,直通车:http://www.cnblogs.com/liushilin/p/5680135.html 当然还有当前我认为最好用的图片缓存加载框架Fresco,

主流图片加载框架ImageLoader、Glide、Picasso、Fresco性能分析---图片加载速度比较

图片加载这种实现繁琐,可复用性又极强的东西,自然是选择使用图片加载框架来快速实现. 像是Android-Universal-Image-Loader.Glide.Picasso.Fresco之类, 但是这时候的烦恼在于,这么多图片加载框架到底谁最实用? 有说Fresco,因为支持WebP,还是用了NDK来加载图片,减少JavaHeap的使用 有Picasso,简洁高效 有说Glide,Picasso升级,可以加载Gif,在Picasso基础上扩展了很多方法 ImageLoader 使用最广,因为

教你写Android ImageLoader框架之基本架构 .

前言 在Android开发中,ImageLoader应该算得上是最重要的开源库之一,由于项目原因(不能使用开源库),前段时间自己也是需要实现一个简单的ImageLoader,因此诞生了这个库,我们暂且叫它为SimpleImageLoader.就目前而言,你上网查ImageLoader资料的时候,基本上能够找到很简单的实现,基本上一个类就把所有的工作给做了,这就显得很不专业了嘛,很多时候我们不只是需要实现功能,而是希望能够在实现功能的同时在设计层面有所提升. SimpleImageLoader分享

关于 ImageLoader 说的够细了。。。

简介ImageLoader(一) 分类: android 开源及第三方项目2014-05-30 12:14 14126人阅读 评论(0) 收藏 举报 ImageLoader 使用该开源项目的之前,先给该开源项目在Github上的地址吧. ImageLoader在GitHub 开始的时候,自己看得也是很头痛,因为许多自己不要的东西上面配置的也多,下面简单给有需要的童鞋介绍下使用吧,暂不涉及太多的东西. 我们看看项目的结构: 这里有四个例子,针对ListView ,Gallery ,GridView

ImageLoader简单分析(三)

其实对于缓存的实现原理及其流程总的来说都很简单,无非就是先从网络加载相关资源,然后用内存缓存或者磁盘缓存把下载到的资源缓存起来:等再次加载相同的资源的时候如果内存缓存或者磁盘缓存还存在就用缓存里面的资源,否则仍然进行网络加载,重复此过程而已.严格说来也没什么可讲的,但是通过研读ImageLoader的源码倒是可以学到很多缓存之外的东西:学学别人的代码怎么设计,资源加载的异步处理机制的灵活使用等等,甚至也可以吸取到一些东西来运用到自己的项目中去.就ImageLoader本身来说,也可以让人了解其工

教你写Android ImageLoader框架之初始配置与请求调度

## 前言 在教你写Android ImageLoader框架之基本架构中我们对SimpleImageLoader框架进行了基本的介绍,今天我们就从源码的角度来剖析ImageLoader的设计与实现.   在我们使用ImageLoader前都会通过一个配置类来设置一些基本的东西,比如加载中的图片.加载失败的图片.缓存策略等等,SimpleImageLoader的设计也是如此.配置类这个比较简单,我们直接看源码吧. ImageLoaderConfig配置 /** * ImageLoader配置类,

教你写Android ImageLoader框架之图片缓存 (完结篇)

在教你写Android ImageLoader框架系列博文中,我们从基本架构到具体实现已经更新了大部分的内容.今天,我们来讲最后一个关键点,即图片的缓存.为了用户体验,通常情况下我们都会将已经下载的图片缓存起来,一般来说内存和本地都会有图片缓存.那既然是框架,必然需要有很好的定制性,这让我们又自然而然的想到了抽象.下面我们就一起来看看缓存的实现吧. 缓存接口 在教你写Android ImageLoader框架之图片加载与加载策略我们聊到了Loader,然后阐述了AbsLoader的基本逻辑,其中

62. ImageLoader源代码-流程分析

一. ImageLoader简介 Android library #1 on GitHub. UIL aims to provide a powerful, flexible and highly customizable instrument for image loading, caching and displaying. It provides a lot of configuration options and good control over the image loading a

Android开源框架ImageLoader:加载图片的三级缓存机制

前言:可从  https://github.com/nostra13/Android-Universal-Image-Loader 下载三级缓存机制的开源框架.下文简单介绍该框架中主要的常用方法,掌握这些方法,基本就可应对多数图片下载的需求. 注意:以下代码为示意代码片断,仔细读一下应能知道怎么用.蓝色表示为开源框架中的类. 1.初始化ImageLoader类对象: ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.