關(guān)于圖片庫的封裝相關(guān)的文章早已經(jīng)看到過.圖片庫的封裝可以使得調(diào)用者不知道,底層的具體實現(xiàn),即使我們換了圖片加載庫,上層處的代碼感知不到無需修改.
如果不做封裝的話,像下面這樣直接使用的話:
Glide.with(iv.getContext())
.load(carSeries.getPicurl())
.placeholder(R.drawable.ic_default_210_160)
.into(iv);
一旦你換了圖片加載庫,比如你想要用 Picasso ,這樣涉及到圖片加載的地方,你都得去改動代碼,這顯然是不現(xiàn)實的.
今天趁著有些空閑特意實踐了下.知道和自己動手實踐還是有差別的,更能發(fā)現(xiàn)一些問題.
紙上得來終覺淺 絕知此事要躬行
ImageLoader 接口定義對外調(diào)用的統(tǒng)一方法
public interface ImageLoader {
public void displayImage(ImageView iv, String imageUrl);
public void displayImage(ImageView iv, String imageUrl, DisplayOption option);
public static class DisplayOption {
public static final int NONE = -1;
/**
* 加載失敗的資源id
*/
public int loadErrorResId = NONE;
/**
* 占位資源id
*/
public int placeHolderResId = NONE;
}
}
具體的實現(xiàn)類
class GlideImageLoader implements ImageLoader {
private RequestManager mRequestManager;
public GlideImageLoader(Context context) {
mRequestManager = Glide.with(context);
}
@Override
public void displayImage(ImageView iv, String imageUrl) {
displayImage(iv, imageUrl, null);
}
@Override
public void displayImage(ImageView iv, String imageUrl, DisplayOption option) {
DrawableTypeRequest<String> drawableTypeRequest = mRequestManager.load(imageUrl);
if (option != null) {
if (option.placeHolderResId != DisplayOption.NONE && option.loadErrorResId != DisplayOption.NONE) {
drawableTypeRequest.placeholder(option.placeHolderResId)
.error(option.loadErrorResId)
.into(iv);
} else if (option.placeHolderResId != DisplayOption.NONE) {
drawableTypeRequest.placeholder(option.placeHolderResId)
.into(iv);
} else if (option.loadErrorResId != DisplayOption.NONE) {
drawableTypeRequest.error(option.placeHolderResId)
.into(iv);
}
} else {
drawableTypeRequest.into(iv);
}
}
}
統(tǒng)一獲取實例方法
public class ImageLoaderFactory {
private static volatile ImageLoader mImageLoader;
public static void init(Context context) {
if (mImageLoader == null) {
synchronized (ImageLoaderFactory.class) {
if (mImageLoader == null) {
mImageLoader = new GlideImageLoader(context);
}
}
}
}
public static ImageLoader getInstance() {
if (mImageLoader == null) {
throw new NullPointerException("you should call method init() first in application onCreate() method");
}
return mImageLoader;
}
}
附Picasso實現(xiàn):
public class PicassoImageLoader implements ImageLoader {
private Picasso mPicasso;
public PicassoImageLoader(Context context) {
mPicasso = Picasso.with(context);
}
@Override
public void displayImage(ImageView iv, String imageUrl) {
mPicasso.load(imageUrl).into(iv);
}
@Override
public void displayImage(ImageView iv, String imageUrl, DisplayOption option) {
if (option != null) {
if (option.placeHolderResId != DisplayOption.NONE && option.loadErrorResId != DisplayOption.NONE) {
mPicasso.load(imageUrl)
.placeholder(option.placeHolderResId)
.error(option.loadErrorResId)
.into(iv);
} else if (option.placeHolderResId != DisplayOption.NONE) {
mPicasso.load(imageUrl)
.placeholder(option.placeHolderResId)
.into(iv);
} else if (option.loadErrorResId != DisplayOption.NONE) {
mPicasso.load(imageUrl)
.error(option.placeHolderResId)
.into(iv);
}
}
}else{
mPicasso.load(imageUrl).into(iv);
}
}
以上其實就是策略模式的具體實踐
策略模式(Strategy Pattern):定義了算法族,分別封裝起來,算法族中的算法可以互相可以替換。讓算法的變化獨立于使用算法的客戶。
ImageLoaderFactory 中的 ImageLoader 可以視為一個算法族,而 GlideImageLoader 、PicassoImageLoader 可視為具體的算法實現(xiàn),他們構(gòu)成了ImageLoader 這個算法族,算法互相之間可以替換。