图片加载框架的打造(四)-封装-完善-总结

Posted by 夏敏的博客 on July 18, 2017

上一章链接 简单图片加载框架的打造(三)-加载器缓存器设计

几个关键的类都设计完了,该我们封装打通的时候呢,我一直喜欢RESTful风格,况且现在是2017年代码调用还不链式不能忍.

看一下我们最终希望调用的方式.

SherlockImageLoader.with(this)
        .setUrl("http://img.my.csdn.net/uploads/201407/26/1406382765_7341.jpg")
        .loadingImage(R.mipmap.ic_launcher_round)
        .errorImage(R.drawable.blog)
        .into(mImageView);

SherlockImageLoader.with(this)
        .setUrl("http://img.my.csdn.net/uploads/201407/26/1406382765_7341.jpg")
        .loadingImage(R.mipmap.ic_launcher_round)
        .errorImage(R.drawable.blog)
        .into(new SherlockImageLoader.Callback() {
            @Override
            public void onSuccess(Bitmap bitmap, String url) {
                Log.i(TAG, "onSuccess: " + bitmap + " url" + url);
            }
        });

这是一个当前流行的调用风格,我们这个是简单的图片加载框架,没有Glide的功能那么多,只提供了上面显示的这些接口.

with的不是绑定生命周期,而是用来tag,即强制将每次申请都绑定tag,这样我们可以在onDestroy的时候可以取消请求.

ps: Glide的with是使用的注册一个空的Fragment来绑定调用方的生命周期,从而做到不需要请求方主动去取消请求的功能,我们这个框架那样写就复杂多了.with的对象有好多种的.

好了,开始封装

Builder的编写

with(Obj tag)方法肯定是SherlockImageLoader的一个静态方法, 返回一个Builder就行了.

public static RequestBuilder with(Object tag) {
    return new RequestBuilder(tag);
}

这个Builder里面有into方法, 相当于exec or build,

代码如下:

/**
 * @author xiamin
 * @date 7/18/17.
 */
public class RequestBuilder {

    private String url;
    /** 显示设置,要是为空,则使用全局的 */
    private DisplayConfig mDisplayConfig;
    /** 请求tag,供取消请求时使用 */
    private Object requestTag;


    public RequestBuilder(Object requestTag) {
        this.requestTag = requestTag;
    }

    public RequestBuilder withDisplayConfig(DisplayConfig displayConfig) {
        mDisplayConfig = displayConfig;
        return this;
    }

    public RequestBuilder loadingImage(int loadingImage) {
        if (mDisplayConfig == null) {
            mDisplayConfig = new DisplayConfig();
        }
        mDisplayConfig.loadingImage = loadingImage;
        return this;
    }

    public RequestBuilder errorImage(int errorImage) {
        if (mDisplayConfig == null) {
            mDisplayConfig = new DisplayConfig();
        }
        mDisplayConfig.failedImage = errorImage;
        return this;
    }


    public RequestBuilder setUrl(String url) {
        this.url = url;
        return this;
    }

    public void into(ImageView imageView) {
        if (imageView == null) {
            throw new IllegalArgumentException("imageview can not be null");
        }

        BitmapRequest bitmapRequest = new BitmapRequest(imageView, url, null, mDisplayConfig);
        bitmapRequest.setRequestTag(requestTag);
        SherlockImageLoader.getInstance().display(bitmapRequest);
    }

    public void into(SherlockImageLoader.Callback callback) {
        if (callback == null) {
            throw new IllegalArgumentException("callback can not be null");
        }

        BitmapRequest bitmapRequest = new BitmapRequest(null, url, callback, mDisplayConfig);
        bitmapRequest.setRequestTag(requestTag);
        SherlockImageLoader.getInstance().display(bitmapRequest);
    }

}

很简单, 我们提供了上述接口, 然后在在调用方就能像上面那样调用了.

完善

  • 对于Cancel请求, 一个请求可能在走到任何地方的时候被Cancel掉,因此其实我们应该尽可能的在多处关键点进行请求是否已经被Cancel的判断.被Cancel就结束.

  • 对于生命周期的绑定,上面说过了,需要向调用方注册一个空Fragment来进行监听生命周期,此功能暂时未做.

  • 对于错误回调,因为是图片加载,错误我们都’catch’了,没有传递到回调里面

  • 各类型的支持,我们这边只进行了Bitmap的编写,各种Drawable均未支持,这种级别的支持工程量就大了

总结

这个图片框架只是一个简单的图片框架,不过是为了锻炼框架思维所编写,真实情况下我们还是用Picasso,Glide比较好,毕竟JakeWharton牛到爆炸…..

工程路径,里面还有我准备写的数据库lib,还有httplib,只看ImageLoaderlib即可. https://github.com/Jerey-Jobs/Sherlock


本文作者:Anderson/Jerey_Jobs

博客地址 : http://jerey.cn/
简书地址 : Anderson大码渣
github地址 : https://github.com/Jerey-Jobs

作者:Anderson大码渣,欢迎关注我的简书: Anderson大码渣