先从现在面对的情形来看,项目中使用图片加载的地方都是使用的类似下面的语句
- ImageLoader.getInstance().displayImage(imageUrl, imageView,options);
然而现在 ImageLoader 已经停止维护且已经无法满足项目需求,我们需要替换,这时你会发现如果换库的话,所有涉及到的地方都要修改(Android-Universal-Image-Loader 已经和图片加载的业务逻辑严重地耦合在一起了),工作量可见一斑,这就是不封装在切库时面临的窘境!
那怎么解决那?
计算机史上有个万能的解决方案就是,如果原有层面解决不了问题,那么就请再加一层!
- /**
- * Created by soulrelay on 2016/10/11 13:42.
- * Class Note:
- * use this class to load image,single instance
- */
- public class ImageLoaderUtil {
- //图片默认加载类型 以后有可能有多种类型
- public static final int PIC_DEFAULT_TYPE = 0;
- //图片默认加载策略 以后有可能有多种图片加载策略
- public static final int LOAD_STRATEGY_DEFAULT = 0;
- private static ImageLoaderUtil mInstance;
- private BaseImageLoaderStrategy mStrategy;
- public ImageLoaderUtil() {
- mStrategy = new GlideImageLoaderStrategy();
- }
- //单例模式,节省资源
- public static ImageLoaderUtil getInstance() {
- if (mInstance == null) {
- synchronized(ImageLoaderUtil.class) {
- if (mInstance == null) {
- mInstance = new ImageLoaderUtil();
- return mInstance;
- }
- }
- }
- return mInstance;
- }
- /**
- * 统一使用App context
- * 可能带来的问题:http://stackoverflow.com/questions/31964737/glide-image-loading-with-application-context
- *
- * @param url
- * @param placeholder
- * @param imageView
- */
- public void loadImage(String url, int placeholder, ImageView imageView) {
- mStrategy.loadImage(imageView.getContext(), url, placeholder, imageView);
- }
- public void loadGifImage(String url, int placeholder, ImageView imageView) {
- mStrategy.loadGifImage(url, placeholder, imageView);
- }
- public void loadImage(String url, ImageView imageView) {
- mStrategy.loadImage(url, imageView);
- }
- /**
- * 展示图片加载进度
- */
- public void loadImageWithProgress(String url, ImageView imageView, ProgressLoadListener listener) {
- mStrategy.loadImageWithProgress(url, imageView, listener);
- }
- public void loadGifWithProgress(String url, ImageView imageView, ProgressLoadListener listener) {
- mStrategy.loadGifWithProgress(url, imageView, listener);
- }
- /**
- * 策略模式的注入操作
- *
- * @param strategy
- */
- public void setLoadImgStrategy(BaseImageLoaderStrategy strategy) {
- mStrategy = strategy;
- }
- /**
- * 清除图片磁盘缓存
- */
- public void clearImageDiskCache(final Context context) {
- mStrategy.clearImageDiskCache(context);
- }
- /**
- * 清除图片内存缓存
- */
- public void clearImageMemoryCache(Context context) {
- mStrategy.clearImageMemoryCache(context);
- }
- /**
- * 根据不同的内存状态,来响应不同的内存释放策略
- *
- * @param context
- * @param level
- */
- public void trimMemory(Context context, int level) {
- mStrategy.trimMemory(context, level);
- }
- /**
- * 清除图片所有缓存
- */
- public void clearImageAllCache(Context context) {
- clearImageDiskCache(context.getApplicationContext());
- clearImageMemoryCache(context.getApplicationContext());
- }
- /**
- * 获取缓存大小
- *
- * @return CacheSize
- */
- public String getCacheSize(Context context) {
- return mStrategy.getCacheSize(context);
- }
- }
所有需要图片显示的地方使用如下方法进行调用:
总结:外部表现一致,内部灵活处理原则。
- /**
- * 图片加载库的封装演示案例
- * Created by soulrelay on 2016/12/11 19:18
- */
- public class MainActivity extends AppCompatActivity {@BindView(R.id.iv_normal) ImageView ivNormal;@BindView(R.id.iv_gif) ImageView ivGif;@BindView(R.id.iv_gif1) ImageView ivGif1;@Override protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- ButterKnife.bind(this);
- initView();
- }
- private void initView() {
- ImageLoaderUtil.getInstance().loadImage("http://image.sports.baofeng.com/25a3dbb0c99c5e48e52e60941ed230be", R.drawable.bg_default_video_common_small, ivNormal);
- ImageLoaderUtil.getInstance().loadImage("http://image.sports.baofeng.com/19ce5d6ac3b4fff255196f200b1d3079", R.drawable.bg_default_video_common_small, ivGif);
- ImageLoaderUtil.getInstance().loadGifImage("http://image.sports.baofeng.com/19ce5d6ac3b4fff255196f200b1d3079", R.drawable.bg_default_video_common_small, ivGif1);
- }
- }
效果图如下所示:
如果你对策略模式不是很熟,请先参考
首先我们需要抽象出一个图片加载的基础接口 BaseImageLoaderStrategy
基本功能主要包括
- /**
- * Created by soulrelay on 2016/10/11.
- * Class Note:
- * abstract class/interface defined to load image
- * (Strategy Pattern used here)
- */
- public interface BaseImageLoaderStrategy {
- //无占位图
- void loadImage(String url, ImageView imageView);
- void loadImage(String url, int placeholder, ImageView imageView);
- void loadImage(Context context, String url, int placeholder, ImageView imageView);
- void loadGifImage(String url, int placeholder, ImageView imageView);
- void loadImageWithProgress(String url, ImageView imageView, ProgressLoadListener listener);
- void loadGifWithProgress(String url, ImageView imageView, ProgressLoadListener listener);
- //清除硬盘缓存
- void clearImageDiskCache(final Context context);
- //清除内存缓存
- void clearImageMemoryCache(Context context);
- //根据不同的内存状态,来响应不同的内存释放策略
- void trimMemory(Context context, int level);
- //获取缓存大小
- String getCacheSize(Context context);
- }
需要说明的一点是:
然后基于每个图片库的各自方式来进行相应策略的封装,需要使用哪种策略,只需要通过 ImageLoaderUtil 的 setLoadImgStrategy(BaseImageLoaderStrategy strategy) 方法将相应的策略注入,相关类图关系如下所示:
不同的图片加载库实现不同的图片加载策略
这里只是给出 Glide 的图片加载策略类 GlideImageLoaderStrategy 作为参考
- /**
- * Created by soulrelay on 2016/10/11 13:48.
- * Class Note:
- * using Glide} to load image
- */
- public class GlideImageLoaderStrategy implements BaseImageLoaderStrategy {@Override public void loadImage(String url, int placeholder, ImageView imageView) {
- loadNormal(imageView.getContext(), url, placeholder, imageView);
- }@Override public void loadImage(Context context, String url, int placeholder, ImageView imageView) {
- loadNormal(context, url, placeholder, imageView);
- }
- /**
- * 无holder的gif加载
- *
- * @param url
- * @param imageView
- */
- @Override public void loadImage(String url, ImageView imageView) {
- Glide.with(imageView.getContext()).load(url).dontAnimate().placeholder(imageView.getDrawable()).diskCacheStrategy(DiskCacheStrategy.SOURCE).into(imageView);
- }@Override public void loadGifImage(String url, int placeholder, ImageView imageView) {
- loadGif(imageView.getContext(), url, placeholder, imageView);
- }@Override public void loadImageWithProgress(String url, final ImageView imageView, final ProgressLoadListener listener) {
- Glide.with(imageView.getContext()).using(new ProgressModelLoader(new ProgressUIListener() {@Override public void update(final int bytesRead, final int contentLength) {
- imageView.post(new Runnable() {@Override public void run() {
- listener.update(bytesRead, contentLength);
- }
- });
- }
- })).load(url).asBitmap().dontAnimate().listener(new RequestListener() {@Override public boolean onException(Exception e, Object model, Target target, boolean isFirstResource) {
- listener.onException();
- return false;
- }@Override public boolean onResourceReady(Bitmap resource, Object model, Target target, boolean isFromMemoryCache, boolean isFirstResource) {
- listener.onResourceReady();
- return false;
- }
- }).into(imageView);
- }@Override public void loadGifWithProgress(String url, final ImageView imageView, final ProgressLoadListener listener) {
- Glide.with(imageView.getContext()).using(new ProgressModelLoader(new ProgressUIListener() {@Override public void update(final int bytesRead, final int contentLength) {
- imageView.post(new Runnable() {@Override public void run() {
- listener.update(bytesRead, contentLength);
- }
- });
- }
- })).load(url).asGif().skipMemoryCache(true).dontAnimate().listener(new RequestListener() {@Override public boolean onException(Exception e, String model, Target target, boolean isFirstResource) {
- listener.onException();
- return false;
- }@Override public boolean onResourceReady(GifDrawable resource, String model, Target target, boolean isFromMemoryCache, boolean isFirstResource) {
- listener.onResourceReady();
- return false;
- }
- }).into(imageView);
- }@Override public void clearImageDiskCache(final Context context) {
- try {
- if (Looper.myLooper() == Looper.getMainLooper()) {
- new Thread(new Runnable() {@Override public void run() {
- Glide.get(context.getApplicationContext()).clearDiskCache();
- }
- }).start();
- } else {
- Glide.get(context.getApplicationContext()).clearDiskCache();
- }
- } catch(Exception e) {
- e.printStackTrace();
- }
- }@Override public void clearImageMemoryCache(Context context) {
- try {
- if (Looper.myLooper() == Looper.getMainLooper()) { //只能在主线程执行
- Glide.get(context.getApplicationContext()).clearMemory();
- }
- } catch(Exception e) {
- e.printStackTrace();
- }
- }@Override public void trimMemory(Context context, int level) {
- Glide.get(context).trimMemory(level);
- }@Override public String getCacheSize(Context context) {
- try {
- return CommonUtils.getFormatSize(CommonUtils.getFolderSize(Glide.getPhotoCacheDir(context.getApplicationContext())));
- } catch(Exception e) {
- e.printStackTrace();
- }
- return "";
- }
- /**
- * load image with Glide
- */
- private void loadNormal(final Context ctx, final String url, int placeholder, ImageView imageView) {
- /**
- * 为其添加缓存策略,其中缓存策略可以为:Source及None,None及为不缓存,Source缓存原型.如果为ALL和Result就不行.然后几个issue的连接:
- https://github.com/bumptech/glide/issues/513
- https://github.com/bumptech/glide/issues/281
- https://github.com/bumptech/glide/issues/600
- modified by xuqiang
- */
- //去掉动画 解决与CircleImageView冲突的问题 这个只是其中的一个解决方案
- //使用SOURCE 图片load结束再显示而不是先显示缩略图再显示最终的图片(导致图片大小不一致变化)
- final long startTime = System.currentTimeMillis();
- Glide.with(ctx).load(url).dontAnimate().placeholder(placeholder).diskCacheStrategy(DiskCacheStrategy.SOURCE).listener(new RequestListener() {@Override public boolean onException(Exception e, String model, Target target, boolean isFirstResource) {
- return false;
- }@Override public boolean onResourceReady(GlideDrawable resource, String model, Target target, boolean isFromMemoryCache, boolean isFirstResource) {
- return false;
- }
- }).into(imageView);
- }
- /**
- * load image with Glide
- */
- private void loadGif(final Context ctx, String url, int placeholder, ImageView imageView) {
- final long startTime = System.currentTimeMillis();
- Glide.with(ctx).load(url).asGif().dontAnimate().placeholder(placeholder).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.SOURCE).listener(new RequestListener() {@Override public boolean onException(Exception e, String model, Target target, boolean isFirstResource) {
- return false;
- }@Override public boolean onResourceReady(GifDrawable resource, String model, Target target, boolean isFromMemoryCache, boolean isFirstResource) {
- return false;
- }
- }).into(imageView);
- }
- }
来源: http://www.bubuko.com/infodetail-1860440.html