Android架构篇——多版本切换封装(图片库、Map等)

项目开发时,一般都会有图片加载、地图等需求,而这些一般使用第三方库,例如图片加载可能会选择Glide、Picasso、Fresco等其中的一种,地图可供选择的有百度地图、高德地图、华为地图(即将发布),那么怎样将其集成到项目中呢?直接将相关的功能加入到业务逻辑中吗?那么突然有一天要将现有使用换成另一种呢?例如现在图片加载使用的是Glide框架,突然要换成Fresco,此时怎么办?要吭哧吭哧再将相关逻辑再写一遍吗?

当然不能,因为这不符合程序员“懒”的特质,那怎么办?好,那借此机会啰嗦一下面向对象(OOP)设计原则:

面向对象程序几大设计原则

基于以上原则,来封装引入第三方服务,以图片加载为例:

  1. 首先基于依赖倒置原则使用接口实现图片加载的逻辑:
public interface ILoader {
    void load(Context context, ImageView imageView, @DrawableRes int drawableRes);

    void load(Context context, ImageView imageView, String url);

    void load(Context context, ImageView imageView, byte[] image);

    void load(Context context, ImageView imageView, @DrawableRes int drawableRes, @DrawableRes int errorResId, @DrawableRes int placeholderResId);

    void load(Context context, ImageView imageView, String url, @DrawableRes int errorResId, @DrawableRes int placeholderResId);

    void load(Context context, ImageView imageView, byte[] image, @DrawableRes int errorResId, @DrawableRes int placeholderResId);
}
  1. 具体实现由其子类完成:
public class GlideLoader implements ILoader {

    @Override
    public void load(Context context, ImageView imageView, int drawableRes) {
        Glide.with(context)
                .load(drawableRes)
                .into(imageView);
    }

    @Override
    public void load(Context context, ImageView imageView, String url) {
        Glide.with(context)
                .load(url)
                .into(imageView);
    }

    @Override
    public void load(Context context, ImageView imageView, byte[] image) {
        Glide.with(context)
                .load(image)
                .into(imageView);
    }

    @Override
    public void load(Context context, ImageView imageView, int drawableRes, int errorResId, int placeholderResId) {
        Glide.with(context)
                .load(drawableRes)
                .apply(getRequestOptions(errorResId, placeholderResId))
                .into(imageView);
    }

    @Override
    public void load(Context context, ImageView imageView, String url, int errorResId, int placeholderResId) {
        Glide.with(context)
                .load(url)
                .apply(getRequestOptions(errorResId, placeholderResId))
                .into(imageView);
    }

    @Override
    public void load(Context context, ImageView imageView, byte[] image, int errorResId, int placeholderResId) {
        Glide.with(context)
                .load(image)
                .apply(getRequestOptions(errorResId, placeholderResId))
                .into(imageView);
    }
}
  1. 然后统一使用Manager管理:
public class ImageLoader implements ILoader {
    private ILoader mImageLoader;
    private static ImageLoader imageManager;

    private ImageLoader() {
    }

    public static ImageLoader getInstance() {
        if (imageManager == null) {
            synchronized (ImageLoader.class) {
                if (imageManager == null) {
                    imageManager = new ImageLoader();
                }
            }
        }
        return imageManager;
    }

    public void setImageLoader(ILoader imageLoader) {
        mImageLoader = imageLoader;
    }


    @Override
    public void load(Context context, ImageView imageView, int drawableRes) {
        mImageLoader.load(context, imageView, drawableRes);
    }

    @Override
    public void load(Context context, ImageView imageView, String url) {
        mImageLoader.load(context, imageView, url);
    }

    @Override
    public void load(Context context, ImageView imageView, byte[] image) {
        mImageLoader.load(context, imageView, image);
    }

    @Override
    public void load(Context context, ImageView imageView, int drawableRes, int errorResId, int placeholderResId) {
        mImageLoader.load(context, imageView, drawableRes, errorResId, placeholderResId);
    }

    @Override
    public void load(Context context, ImageView imageView, String url, int errorResId, int placeholderResId) {
        mImageLoader.load(context, imageView, url, errorResId, placeholderResId);
    }

    @Override
    public void load(Context context, ImageView imageView, byte[] image, int errorResId, int placeholderResId) {
        mImageLoader.load(context, imageView, image, errorResId, placeholderResId);
    }
}
  1. 使用时先设置setImageLoader(),然后通过ImageLoader直接调用:
//在Application中设置
private void setImageLoader() {
        ImageLoader.getInstance().setImageLoader(new GlideLoader());
}
  1. 全局使用,例如:
@Override 
protected void initView() {
        super.initView();
        ImageLoader.getInstance().load(getContext(), mImgMainActImg, R.mipmap.ic_launcher_round);
}

6.突然技术改变要更换成Picasso,那么直接实现PicassoLoader,设置 ImageLoader.getInstance().setImageLoader(new PicassoLoader())即可,原有逻辑一下也不需要动

备注:Fresco加载图片使用的是自定义View控件加载图片,所以以上ImageView修改为View更佳

回过头来分析下,此图片加载框架封装几乎使用了上述所有的设计原则,也可推广到地图和其他,读者有不同观点或改进建议请留言一起交流一下!

你可能感兴趣的:(Android架构篇——多版本切换封装(图片库、Map等))