雲課堂android端,目前使用的圖片加載庫是UniversalImageLoader(簡稱UIL)。在5.4.0迭代版本中,因首頁又增長了幾個頁面,發現啓動app後,內存暴增,在排查問題後發現,是圖片加載庫的使用方式存在問題,以及該加載庫對內存並不友好。所以在對比Glide後,發下啓動app後,內存有很大改善,決定使用Glide。所以須要將原有的圖片加載庫替換成新的。這套新的方案,須要在將來的幾年中使用,而且可以靈活替換圖片加載庫。java
在工程中發現原來使用UIL儘管被封裝在EduImageLoaderUtil
類中,包括UIL的初始配置以及默認選項。但仍是有些UIL包內的類如ImageLoadingListener
、DisplayImageOptions
暴露在公用方法中,在外部調用的時候傳入。這個嚴重影響了封裝性,不方便後期替換圖片加載庫。android
下面是類圖:api
下面是代碼實現:緩存
類ImageLoaderManager
因爲圖片庫在一個應用中只會選擇一種實現方案,因此這裏的ImageLoader管理類,簡單處理,配有一個默認的實現,一個默認的全局配置,一個默認的圖片加載配置。提供了接口去修改默認的。網絡
package com.netease.framework.imagemodule; import com.netease.framework.annotation.NonNull; import com.netease.framework.imagemodule.glide.GlideImageLoader; /** * ImageLoader管理類,默認的ImageLoader實現是GlideImageLoader。 * 提供一些注入接口,來修改默認實現以及默認配置 * Created by hzchenboning on 2017/10/8. */ public class ImageLoaderManager { private static ImageLoader sImageLoader = new GlideImageLoader(); //默認的ImageLoader實現,Glide private static DisplayImageConfig sDefaultDisPlayImageConfig = new DisplayImageConfig.Builder().build(); private static GlobalImageConfig sGlobalImageConfig = new GlobalImageConfig.Builder().build(); public static ImageLoader getImageLoader() { return sImageLoader; } public static @NonNull GlobalImageConfig getGlobalImageConfig() { return sGlobalImageConfig; } public static @NonNull DisplayImageConfig getDefaultDisPlayImageConfig() { return sDefaultDisPlayImageConfig; } /** * 修改默認的ImageLoader實現類 * @param imageLoader */ public static void setImageLoader(@NonNull ImageLoader imageLoader) { sImageLoader = imageLoader; } /** * 修改默認的每次圖片加載配置項 * @param sDefaultDisPlayImageConfig */ public static void setDefaultDisPlayImageConfig(@NonNull DisplayImageConfig sDefaultDisPlayImageConfig) { ImageLoaderManager.sDefaultDisPlayImageConfig = sDefaultDisPlayImageConfig; } /** * 修改默認的全局配置項 * @param sGlobalImageConfig */ public static void setGlobalImageConfig(@NonNull GlobalImageConfig sGlobalImageConfig) { ImageLoaderManager.sGlobalImageConfig = sGlobalImageConfig; } }
類ImageLoader
app
import android.content.Context; import android.graphics.Bitmap; import android.widget.ImageView; /** * 圖片加載器對外提供的服務接口 * Created by hzchenboning on 17/9/28. */ public interface ImageLoader { /** * 展現圖片 */ void displayImage(Context context, String imageUrl, ImageView imageView); /** * 展現指定尺寸 */ void displayImage(Context context, String imageUrl, ImageView imageView, int width, int height); /** * 根據配置展現圖片 */ void displayImage(Context context, String imageUrl, ImageView imageView, DisplayImageConfig config); /** * 根據配置展現指定大小圖片 */ void displayImage(Context context, String imageUrl, ImageView imageView, DisplayImageConfig config, int width, int height); /** * 展現圖片,而且監聽圖片加載回調 */ <R> void displayImage(Context context, String imageUrl, ImageView imageView, ResourceListener<R> listener); /** * 根據配置展現圖片,而且監聽圖片加載回調 */ <R> void displayImage(Context context, String imageUrl, ImageView imageView, DisplayImageConfig config, ResourceListener<R> listener); /** * 展現高斯模糊圖片 * @param radius 高斯模糊半徑(像素),不包含中心點的像素,取值範圍[1, 50] * @param sigma 高斯模糊標準差 */ void displayBlurImage(Context context, String imageUrl, ImageView imageView, int radius, int sigma); /** * 展現圓形圖片 * 圓形的半徑爲圖片的Math.min(width, height)/2 */ void displayCircleImage(Context context, String imageUrl, ImageView imageView); /** * 下載圖片 */ <R> void loadImage(Context context, String imageUrl, ResourceListener<R> resourceListener); /** * 根據配置下載圖片 */ <R> void loadImage(Context context, String imageUrl, DisplayImageConfig config, ResourceListener<R> resourceListener); /** * 從緩存中(內存、磁盤)獲取圖片 */ Bitmap getBitmapFromCache(String url); interface ResourceListener<R> { void onResourceReady(R resouce); } }
類DisplayImageConfig
ide
import com.netease.edu.framework.R; /** * 每次圖片加載的配置項 * Created by hzchenboning on 17/10/9. */ public class DisplayImageConfig { int imageResOnLoading; int imageResOnFail; Priority priority; boolean cacheOnDisk; boolean cacheOnMemory; boolean needThumbnail; float thumbnail; BitmapTransformation transformation; private DisplayImageConfig(Builder builder) { this.imageResOnLoading = builder.imageResOnLoading; this.imageResOnFail = builder.imageResOnFail; this.priority = builder.priority; this.cacheOnDisk = builder.cacheOnDisk; this.cacheOnMemory = builder.cacheOnMemory; this.needThumbnail = builder.needThumbnail; this.thumbnail = builder.thumbnail; this.transformation = builder.transformation; } public int getImageResOnLoading() { return imageResOnLoading; } public int getImageResOnFail() { return imageResOnFail; } public Priority getPriority() { return priority; } public boolean isCacheOnDisk() { return cacheOnDisk; } public boolean isCacheOnMemory() { return cacheOnMemory; } public boolean isNeedThumbnail() { return needThumbnail; } public float getThumbnail() { return thumbnail; } public static class Builder { int imageResOnLoading = R.drawable.default_img;//加載中顯示的圖片 int imageResOnFail = R.drawable.default_img;//加載失敗後顯示的圖片 Priority priority = Priority.NORMAL;//加載優先級 boolean cacheOnDisk = true; boolean cacheOnMemory = true; boolean needThumbnail = true;//是否先顯示縮略圖 float thumbnail = 0.1f;//縮略圖爲原圖的十分之一 BitmapTransformation transformation = BitmapTransformation.none; public Builder setImageResOnLoading(int imageResOnLoading) { this.imageResOnLoading = imageResOnLoading; return this; } public Builder setImageResOnFail(int imageResOnFail) { this.imageResOnFail = imageResOnFail; return this; } public Builder setPriority(Priority priority) { this.priority = priority; return this; } public Builder setCacheOnDisk(boolean cacheOnDisk) { this.cacheOnDisk = cacheOnDisk; return this; } public Builder setCacheOnMemory(boolean cacheOnMemory) { this.cacheOnMemory = cacheOnMemory; return this; } public Builder setNeedThumbnail(boolean needThumbnail) { this.needThumbnail = needThumbnail; return this; } public Builder setThumbnail(float thumbnail) { this.thumbnail = thumbnail; return this; } public Builder setTransformation(BitmapTransformation transformation) { this.transformation = transformation; return this; } public DisplayImageConfig build() { return new DisplayImageConfig(this); } } public enum Priority { IMMEDIATE, //0ms LOW, //300ms NORMAL, //100ms HIGH //50ms } /** * 每一個新增的轉換,須要增長對應的描述 * 新增的命名就按照circleCrop、roundCrop */ public enum BitmapTransformation { none, //(無變化) } }
類GlobalImageConfig
ui
import android.support.annotation.IntDef; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * 全局的圖片加載配置 * Created by hzchenboning on 17/10/9. */ public class GlobalImageConfig { //--------- 如下是接口及常量 ------------- @Retention(RetentionPolicy.SOURCE) @IntDef({HIGH_IMAGE_QUALITY, NORMAL_IMAGE_QUALITY, LOW_IMAGE_QUALITY}) private @interface ImageQualityMode {} public static final int HIGH_IMAGE_QUALITY = 100; public static final int NORMAL_IMAGE_QUALITY = 80; public static final int LOW_IMAGE_QUALITY = 50; //磁盤緩存文件 250MB private static final String DEFAULT_DISK_CACHE_DIR = "image_manager_disk_cache"; private static final int DEFAULT_DISK_CACHE_SIZE = 250 * 1024 * 1024; //--------- 以上是接口及常量 ------------- public static boolean NEED_ADJUST_IMAGE_QUALITY = false; private static int sImageQuality = HIGH_IMAGE_QUALITY; private final boolean useExternalDiskCacheDir; private final String cacheFolderName; private final int diskCacheSize; private final int memoryCacheSize; public GlobalImageConfig(boolean useExternalDiskCacheDir, String cacheFolderName, int diskCacheSize, int memoryCacheSize) { this.useExternalDiskCacheDir = useExternalDiskCacheDir; this.cacheFolderName = cacheFolderName; this.diskCacheSize = diskCacheSize; this.memoryCacheSize = memoryCacheSize; } public static int getImageQuality() { return sImageQuality; } public static void setImageQuality(@ImageQualityMode int quality) { sImageQuality = quality; } public boolean isUseExternalDiskCacheDir() { return useExternalDiskCacheDir; } public String getCacheFolderName() { return cacheFolderName; } public int getDiskCacheSize() { return diskCacheSize; } public int getMemoryCacheSize() { return memoryCacheSize; } public static class Builder { boolean useExternalDiskCacheDir = true; // 默認使用外部存儲卡,false的話使用內部 String cacheFolderName = DEFAULT_DISK_CACHE_DIR; int diskCacheSize = DEFAULT_DISK_CACHE_SIZE; int memoryCacheSize = 0;//若是爲0,交給第三方去計算最合適的大小 public Builder setUseExternalDiskCacheDir(boolean useExternalDiskCacheDir) { this.useExternalDiskCacheDir = useExternalDiskCacheDir; return this; } public Builder setCacheFolderName(String cacheFolderName) { this.cacheFolderName = cacheFolderName; return this; } public Builder setDiskCacheSize(int diskCacheSize) { this.diskCacheSize = diskCacheSize; return this; } public Builder setMemoryCacheSize(int memoryCacheSize) { this.memoryCacheSize = memoryCacheSize; return this; } public GlobalImageConfig build() { return new GlobalImageConfig(useExternalDiskCacheDir, cacheFolderName, diskCacheSize, memoryCacheSize); } } }
本文來自網易雲社區,經做者陳柏寧受權發佈。this
原文地址:應用圖片加載服務與第三方實現庫的解耦url
更多網易研發、產品、運營經驗分享請訪問網易雲社區。