网络图片加载的封装-(从零开始搭建android框架系列(4))
2017-07-12 09:06
736 查看
网络图片加载的封装-(从零开始搭建android框架系列(4))
标签: 框架android2016-05-12 16:44 1043人阅读 评论(0) 收藏 举报
分类:
从零开始搭建android框架系列(10)
版权声明:本文为博主原创文章,未经博主允许不得转载。
目录(?)[+]
本篇文章项目github地址:MVPCommon
本文章原地址:简书博客
1 有哪些常用的图片加载库?
当下使用的主要有Piccaso、Fresco、Android-Universal-Image-Loader、Glide、Volley这五个图片加载框架。
关于这些图片加载框架的对比,网上可以找到很多文章。这里不做过多赘述。具体请参考5中的参考链接,肯定会对你有帮助。
2 为什么要封装?
这个段落的答案,摘抄自Stormzhang的文章 如何正确使用开源项目?计算机史上有个万能的解决方案就是,如果原有层面解决不了问题,那么就请再加一层!
对于开源项目,我们知道有些库设计的确实很棒,使用者调用起来非常方便,一行代码直接搞定,拿图片加载库 Picasso 举个例子:
Picasso.with(context).load(imageUrl).into(imageView); ``` 使用起来是不是特简单?你也许问我,都封装的这么好了还用得着再封装一层么?那你错了,哪怕他已经很完美了,我都会这么做:1
2
3
4
5
1
2
3
4
5
public class ImageLoader {
public static void with(Context context, String imageUrl, ImageView imageView) {
Picasso.with(context).load(imageUrl).into(imageView);
}
}
这样我所有项目调用的方式直接就是 ImageLoader.with() ,这样做的好处是: 入口统一,所有图片加载都在这一个地方管理,一目了然,即使有什么改动我也只需要改这一个类就可以了。 随着你们业务的需求,发现 Picasso 这个图片加载库已经满足不了你们了,你们需要换成 Fresco ,如果你没有封装一层的话,想要替换这个库那你要崩溃了,要把所有调用 Picasso 的地方都改一遍,而如果你中间封装了一层,那真的非常轻松,三天两头的换一次也没问题。 这就是所谓的外部表现一致,内部灵活处理原则。 **** ####3 有哪些需求? 这里提供我平常开发用到的两个需求: **3.1 图片封装,提供统一入口。**封装成熟的图片框架,也就解决了这些问题:(内存缓存,磁盘缓存,网络加载的结合,利用采样率对图片进行一定的压缩,高效加载bitmap,图片的加载策略,缓存策略(LRU),图片错位 ,优化列表的卡顿) **3.2 提供wifi下加载图片开关,非wifi下显示占位图片。** **** ####4 怎么实现图片封装? **4.1 整体目录** 在我的mvp搭建的项目中,imageloader放在和activity,fragment同级的widget下面。当然后续也会不断的添加widget(小控件),比如这里的loading(加载),netstatus(网络状态监听),progress(Material 进度条),swipeback(滑动返回)等。 ![](http://upload-images.jianshu.io/upload_images/1833901-cc796f6e9d9c44da.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) **4.2 ImageUtil类** 作为整个ImageLoader的公共访问入口,以后使用的方式,将会是1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ImageLoader imageLoader =new ImageLoader.Builder().url(“img url”).imgView(mImgView).build();
ImageLoaderUtil.getInstance().loadImage(context,imageLoader);
这种形式。可以看到ImageUtil提供的是单例模式,进行了封装。全局应该只提供一个ImageLoader的实例,因为图片加载中又有线程池,缓存系统和网络请求等,很消耗资源,所以不可能让它构造多个实例。1
2
1
2
package edu.com.mvplibrary.ui.widget.imageloader;
import android.content.Context;
/**
* Created by Anthony on 2016/3/3.
* Class Note:use this class to load image,single instance
*/
public class ImageLoaderUtil {
public static final int PIC_LARGE = 0; public static final int PIC_MEDIUM = 1; public static final int PIC_SMALL = 2; public static final int LOAD_STRATEGY_NORMAL = 0; public static final int LOAD_STRATEGY_ONLY_WIFI = 1; private static ImageLoaderUtil mInstance; private BaseImageLoaderProvider mProvider; private ImageLoaderUtil(){ mProvider =new GlideImageLoaderProvider(); }
//single instance
public static ImageLoaderUtil getInstance(){
if(mInstance ==null){
synchronized (ImageLoaderUtil.class){
if(mInstance == null){
mInstance = new ImageLoaderUtil();
return mInstance;
}
}
}
return mInstance;
}
public void loadImage(Context context,ImageLoader img){ mProvider.loadImage(context,img); }
}
**4.3 BaseImageLoaderProvider类** 可以看到我们ImageUtil中是采用这个类的loadImage方法去加载图片的。这里是一个抽象方法,提供空的实现。由具体的子类(GlideImageLoaderProvider)去实现。1
2
3
1
2
3
package edu.com.mvplibrary.ui.widget.imageloader;
import android.content.Context;
/**
* Created by Anthony on 2016/3/3.
* Class Note:
* abstract class defined to load image
*/
public abstract class BaseImageLoaderProvider {
public abstract void loadImage(Context ctx, ImageLoader img);
}
**4.4 GlideImageLoaderProvider类** 是BaseImageLoaderProvider的实现类,完成具体的加载图片操作。这里面会有wifi下加载图片的判断。具体判断将放在util工具类中进行实现。这里也是利用图片加载库Glide进行实现。后期如果工程项目决定使用其他的图片加载框架,当然可以采用其他类继承BaseImageLoaderProvider。1
2
3
1
2
3
package edu.com.mvplibrary.ui.widget.imageloader;
import android.content.Context;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.model.stream.StreamModelLoader;
import Java.io.IOException;
import java.io.InputStream;
import edu.com.mvplibrary.AbsApplication;
import edu.com.mvplibrary.util.AppUtils;
import edu.com.mvplibrary.util.SettingUtils;
/**
* Created by Anthony on 2016/3/3.
* Class Note:
* provide way to load image
*/
public class GlideImageLoaderProvider extends BaseImageLoaderProvider {
@Override
public void loadImage(Context ctx, ImageLoader img) {
boolean flag= SettingUtils.getOnlyWifiLoadImg(ctx); //如果不是在wifi下加载图片,直接加载 if(!flag){ loadNormal(ctx,img); return; } int strategy =img.getStrategy(); if(strategy == ImageLoaderUtil.LOAD_STRATEGY_ONLY_WIFI){ int netType = AppUtils.getNetWorkType(AbsApplication.app()); //如果是在wifi下才加载图片,并且当前网络是wifi,直接加载 if(netType == AppUtils.NETWORKTYPE_WIFI) { loadNormal(ctx, img); } else { //如果是在wifi下才加载图片,并且当前网络不是wifi,加载缓存 loadCache(ctx, img); } }else{ //如果不是在wifi下才加载图片 loadNormal(ctx,img); } } /** * load image with Glide */ private void loadNormal(Context ctx, ImageLoader img) { Glide.with(ctx).load(img.getUrl()).placeholder(img.getPlaceHolder()).into(img.getImgView()); } /** *load cache image with Glide */ private void loadCache(Context ctx, ImageLoader img) { Glide.with(ctx).using(new StreamModelLoader<String>() { @Override public DataFetcher<InputStream> getResourceFetcher(final String model, int i, int i1) { return new DataFetcher<InputStream>() { @Override public InputStream loadData(Priority priority) throws Exception { throw new IOException(); } @Override public void cleanup() { } @Override public String getId() { return model; } @Override public void cancel() { } }; } }).load(img.getUrl()).placeholder(img.getPlaceHolder()).diskCacheStrategy(DiskCacheStrategy.ALL).into(img.getImgView()); }
}
**4.5 ImageLoader类** 在ImageUtil的load方法中进行图片加载,第一个参数是Context,那么第二个参数呢?正是这里的ImageLoader,采用Builder建造者模式。Builder模式可以将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以构建不同的对象。 **why builder pattern?** 因为在图片加载中,会处理到的数据必定有图片的url,必定有ImageView的实例,可能有加载策略(是否wifi下加载),可能有图片加载类型(大图,中图,小图),也会有图片加载没有成功时候的占位符。那么这么多数据操作,所以用到了Builder模式,一步一步的创建一个复杂对象的创建者模式,它允许用户在不知道内部构建细节的情况下,可以更精细的控制对象的构建流程。比如这里的ImageLoader。1
2
3
4
5
6
7
1
2
3
4
5
6
7
package edu.com.mvplibrary.ui.widget.imageloader;
import android.widget.ImageView;
import edu.com.mvplibrary.R;
/**
* Created by Anthony on 2016/3/3.
* Class Note:
* encapsulation of ImageView,Build Pattern used
*/
public class ImageLoader {
private int type; //类型 (大图,中图,小图)
private String url; //需要解析的url
private int placeHolder; //当没有成功加载的时候显示的图片
private ImageView imgView; //ImageView的实例
private int strategy;//加载策略,是否在wifi下才加载
private ImageLoader(Builder builder) { this.type = builder.type; this.url = builder.url; this.placeHolder = builder.placeHolder; this.imgView = builder.imgView; this.strategy = builder.strategy; } public int getType() { return type; } public String getUrl() { return url; } public int getPlaceHolder() { return placeHolder; } public ImageView getImgView() { return imgView; } public int getStrategy() { return strategy; } public static class Builder { private int type; private String url; private int placeHolder; private ImageView imgView; private int strategy; public Builder() { this.type = ImageLoaderUtil.PIC_SMALL; this.url = ""; this.placeHolder = R.drawable.default_pic_big; this.imgView = null; this.strategy = ImageLoaderUtil.LOAD_STRATEGY_NORMAL; } public Builder type(int type) { this.type = type; return this; } public Builder url(String url) { this.url = url; return this; } public Builder placeHolder(int placeHolder) { this.placeHolder = placeHolder; return this; } public Builder imgView(ImageView imgView) { this.imgView = imgView; return this; } public Builder strategy(int strategy) { this.strategy = strategy; return this; } public ImageLoader build() { return new ImageLoader(this); } }
}
“`
5 参考链接
Android几个图片缓存原理、特性对比
Introduction to Glide, Image Loader Library for Android, recommended by Google
FaceBook推出的Android图片加载库-Fresco
StackOverflow–>Picasso v/s Imageloader v/s Fresco vs Glide
本篇文章项目github地址:MVPCommon
相关文章推荐
- 网络图片加载的封装【从零开始搭建android框架系列(4)】
- 网络图片加载的封装-(从零开始搭建android框架系列(4))
- 网络图片加载的封装-(从零开始搭建android框架系列(4))
- 网络图片加载的封装【从零开始搭建android框架系列(4)】
- Android批量图片加载经典系列——使用xutil框架缓存、异步加载网络图片
- Android批量图片加载经典系列——使用xutil框架缓存、异步加载网络图片
- Android批量图片加载经典系列——采用二级缓存、异步加载网络图片
- Android批量图片加载经典系列——afinal框架实现图片的异步缓存加载
- Android 网络通信框架Volley简介以及获取JSON对象和图片加载例子
- Android_开源框架_AndroidUniversalImageLoader网络图片加载
- Android批量图片加载经典系列——afinal框架实现图片的异步缓存加载
- Android_开源框架_AndroidUniversalImageLoader网络图片加载
- [转]Android_开源框架_AndroidUniversalImageLoader网络图片加载
- **Android_开源框架_AndroidUniversalImageLoader网络图片加载**
- Android 网络图片加载之cude 框架
- Android 网络图片加载之cude 框架
- Android利用Volley框架加载网络图片
- Android开源框架--AndroidUniversalImageLoader网络图片加载
- Android_开源框架_AndroidUniversalImageLoader网络图片加载
- Android循环滚动广告条的完美实现,封装方便,平滑过渡,从网络加载图片,点击广告进入对应网址