1. 程式人生 > >基於Glide的二次封裝

基於Glide的二次封裝

更多程式碼可以查詢本人GitHub:歡迎閱讀,star點起來。
Glide二次封裝庫原始碼

前言

為什麼選擇Glide?

  • Glide 輕量級
  • 速度快
  • 可以根據所需載入圖片的大小自動適配所需解析度的圖
  • 支援多種格式圖片(靜態webp,動態gif,jpeg,jpg,png)
  • 支援多種資料來源圖片(url,drawable,src,file,asserts,raw)
  • Google主導

已經很方便了,為啥還要封裝?

  • 避免以後換框架的時候需要改的地方太多。如果封裝了只需要改封裝的方法而不會影響到所有的程式碼。
  • 入口統一,所有圖片載入都在這一個地方管理,一目瞭然,即使有什麼改動我也只需要改這一個類就可以了。
  • 雖然現在的第三方庫已經非常好用,但是如果我們看到第三方庫就拿來用的話,很可能在第三方庫無法滿足業務需求或者停止維護的時候,發現替換庫,工作量可見一斑。這就是不封裝在切庫時面臨的窘境!
  • 外部表現一致,內部靈活處理原則

初識Glide

Glide配置

1、 在build.gradle中新增依賴:

dependencies {
  compile 'com.github.bumptech.glide:glide:3.7.0'
  compile 'com.android.support:support-v4:19.1.0'
}

2、混淆

-keep public
class * implements com.bumptech.glide.module.GlideModule -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { **[] $VALUES; public *; } # for DexGuard only -keepresourcexmlelements manifest/application/meta-data@value=GlideModule

3、許可權
如果是聯網獲取圖片或者本地儲存需要新增以下許可權:

<uses-permission
android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Glide基本使用

Glide使用一個流介面(Fluent Interface)。用Glide完成一個完整的圖片載入功能請求,需要向其構造器中至少傳入3個引數,分別是:

  • with(Context context)- Context是許多Android API需要呼叫的, Glide也不例外。這裡Glide非常方便,你可以任意傳遞一個Activity或者Fragment物件,它都可以自動提取出上下文。
  • load(String imageUrl) - 這裡傳入的是你要載入的圖片的URL,大多數情況下這個String型別的變數會連結到一個網路圖片。
  • into(ImageView targetImageView) - 將你所希望解析的圖片傳遞給所要顯示的ImageView。

example:

ImageView targetImageView = (ImageView) findViewById(R.id.imageView);
String internetUrl = "http://i.imgur.com/DvpvklR.png";

Glide
    .with(context)
    .load(internetUrl)
    .into(targetImageView);

如何進行二次封裝

明白了為什麼封裝以及基本原理,接下來我們就要開工,大幹一場。

先看一下本人封裝後的基本使用樣式:

ImageLoader.with(this)
    .url("http://img.yxbao.com/news/image/201703/13/7bda462477.gif")
    .placeHolder(R.mipmap.ic_launcher,false)
    .rectRoundCorner(30, R.color.colorPrimary)
    .blur(40)
    .into(iv_round);

更多屬性我們後再詳細講解使用,主要先來看看具體的封裝。

先看一下uml:

這裡寫圖片描述

使用者只需要關心ImageLoader就好了,就算裡面封裝的庫更換、更新也沒關係,因為對外的介面是不變的。實際操作中是由實現了ILoader的具體類去操作的,這裡我們只封裝了GlideLoader,其實所有操作都是由ImageLoader下發指令,由GlideLoader具體去實現的。這裡如果想封裝別的第三方庫,只需要實現ILoader自己去完成裡面的方法。

初始化

    public static int CACHE_IMAGE_SIZE = 250;

    public static void init(final Context context) {
        init(context, CACHE_IMAGE_SIZE);
    }

    public static void init(final Context context, int cacheSizeInM) {
        init(context, cacheSizeInM, MemoryCategory.NORMAL);
    }

    public static void init(final Context context, int cacheSizeInM, MemoryCategory memoryCategory) {
        init(context, cacheSizeInM, memoryCategory, true);
    }

    /**
     * @param context        上下文
     * @param cacheSizeInM   Glide預設磁碟快取最大容量250MB
     * @param memoryCategory 調整記憶體快取的大小 LOW(0.5f) / NORMAL(1f) / HIGH(1.5f);
     * @param isInternalCD   true 磁碟快取到應用的內部目錄 / false 磁碟快取到外部存
     */
    public static void init(final Context context, int cacheSizeInM, MemoryCategory memoryCategory, boolean isInternalCD) {
        ImageLoader.context = context;
        GlobalConfig.init(context, cacheSizeInM, memoryCategory, isInternalCD);
    }

從這裡可以看出我們提供了四個構造器,這裡註釋詳細說明了所有引數的用法及意義。

除了初始化,我們還需要在Application中重寫以下方法:

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        // 程式在記憶體清理的時候執行
        ImageLoader.trimMemory(level);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        // 低記憶體的時候執行
        ImageLoader.clearAllMemoryCaches();
    }

上面這兩個方法會在下面ImageLoader中介紹到。

你所關心的類–ImageLoader

ImageLoader是封裝好所有的方法供使用者使用的,讓我們看看都有什麼方法:

  • ImageLoader.init(Context context) //初始化
  • ImageLoader.trimMemory(int level);
  • ImageLoader.clearAllMemoryCaches();
  • ImageLoader.getActualLoader(); //獲取當前的loader
  • ImageLoader.with(Context context) //載入圖片
  • ImageLoader.saveImageIntoGallery(DownLoadImageService downLoadImageService) // 儲存圖片到相簿
  • ImageLoader.pauseRequests() //取消請求
  • ImageLoader.resumeRequests() //回覆的請求(當列表在滑動的時候,呼叫pauseRequests()取消請求,滑動停止時,呼叫resumeRequests()恢復請求 等等)
  • ImageLoader.clearDiskCache()//清除磁碟快取(必須在後臺執行緒中呼叫)
  • ImageLoader.clearMomoryCache(View view) //清除指定view的快取
  • ImageLoader.clearMomory() // 清除記憶體快取(必須在UI執行緒中呼叫)

圖片的各種設定資訊–SingleConfig

我們所設定圖片的所有屬性都寫在這個類裡面。下面我們詳細的看一下:

  • url(String url) //url
  • file(String filePath) //載入SD卡資源
  • file(File file) //載入SD卡資源
  • res(int resId) //載入drawable資源
  • content(String contentProvider) //載入ContentProvider資源
  • raw(String rawPath) //載入raw資源
  • asserts(String assertspath) //載入asserts資源
  • thumbnail(float thumbnail)//縮圖
  • rectRoundCorner(int rectRoundRadiusf) //形狀為圓角矩形時的圓角半徑
  • priority(int priority) //優先順序
  • error(int errorResId) //錯誤佔位圖
  • asSquare() //形狀為正方形
  • colorFilter(int color) //顏色濾鏡
  • diskCacheStrategy(DiskCacheStrategy diskCacheStrategy) //DiskCacheStrategy.NONE :不快取圖片 /DiskCacheStrategy.SOURCE :快取圖片原始檔/DiskCacheStrategy.RESULT:快取修改過的圖片/DiskCacheStrategy.ALL:快取所有的圖片,預設
    ignoreCertificateVerify(boolean ignoreCertificateVerify) // https是否忽略校驗
  • asCircle()//載入圓形圖片
  • placeHolder(int placeHolderResId) //佔位圖
  • override(int oWidth, int oHeight) //載入圖片時設定解析度 a
  • scale(int scaleMode) // CENTER_CROP等比例縮放圖片,直到圖片的狂高都大於等於ImageView的寬度,然後擷取中間的顯示 ; FIT_CENTER 等比例縮放圖片,寬或者是高等於ImageView的寬或者是高 預設:FIT_CENTER
  • animate(int animationId ) 引入動畫
  • animate( Animation animation) 引入動畫
  • animate(ViewPropertyAnimation.Animator animato) 引入動畫
  • asBitmap(BitmapListener bitmapListener)// 使用bitmap不顯示到imageview
  • into(View targetView) //展示到imageview
  • colorFilter(int filteColor) //顏色濾鏡
  • blur(int blurRadius) //高斯模糊
  • brightnessFilter(float level) //調節圖片亮度
  • grayscaleFilter() //黑白效果
  • swirlFilter() //漩渦效果
  • toonFilter() //油畫效果
  • sepiaFilter() //水墨畫效果
  • contrastFilter(float constrasrLevel) //銳化效果
  • invertFilter() //膠片效果
  • pixelationFilter(float pixelationLevel) //馬賽克效果
  • sketchFilter() // //素描效果
  • vignetteFilter() //暈映效果

中轉站–GlobalConfig

GlobalConfig類非常簡單主要是選擇Loader的操作,之所以用到這個類是因為方便以後擴充套件。今後我們如果需要使用其他的圖片載入框架,只需要繼承ILoader,然後在GlobalConfig中配置即可。

public class GlobalConfig {
    public static void init(Context context, int cacheSizeInM, 
        getLoader().init(context, cacheSizeInM, memoryCategory, isInternalCD);

    }

    public static ILoader getLoader() {

        if (loader == null) {
            //這裡只做了glide的封裝
            loader = new GlideLoader();
        }
        //可以接著做fresco或者picasso

        return loader;
    }
{

最終的執行者–GlideLoader

GlideLoader實現ILoader介面。在使用的時候我們雖然不用關心這個類,但是瞭解一下主要做了什麼功能還是必要的。
GlideLoader中主要做了兩件事,一個是初始化的實現,一個是出口方法的實現。

初始化的實現

我們在application中呼叫

 ImageLoader.init(getApplicationContext());

會最終呼叫到下面這個方法,最終的操作都是在這裡進行的

public class GlideLoader implements ILoader {

    /**
     * @param context        上下文
     * @param cacheSizeInM   Glide預設磁碟快取最大容量250MB
     * @param memoryCategory 調整記憶體快取的大小 LOW(0.5f) / NORMAL(1f) / HIGH(1.5f);
     * @param isInternalCD   true 磁碟快取到應用的內部目錄 / false 磁碟快取到外部存
     */
    @Override
    public void init(Context context, int cacheSizeInM, MemoryCategory memoryCategory, boolean isInternalCD) {
        Glide.get(context).setMemoryCategory(memoryCategory); //如果在應用當中想要調整記憶體快取的大小,開發者可以通過如下方式:
        GlideBuilder builder = new GlideBuilder(context);
        if (isInternalCD) {
            builder.setDiskCache(new InternalCacheDiskCacheFactory(context, cacheSizeInM * 1024 * 1024));
        } else {
            builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, cacheSizeInM * 1024 * 1024));
        }
    }
}

出口方法的實現

不管最終我們使用的是into() 還是 asBitmap()最終都會呼叫GlideLoader的request()方法。

request()方法裡面我們主要思路是拿到DrawableTypeRequest,然後根據SingleConfig中的配置資訊進行設定。

@Override
    public void request(final SingleConfig config) {
        RequestManager requestManager = Glide.with(config.getContext());
        DrawableTypeRequest request = getDrawableTypeRequest(config, requestManager);
    }

比如:設定圖片伸縮
方法如下:

            //先拿到之前的配置資訊。
            int scaleMode = config.getScaleMode();

            //然後根據配置資訊去對request進行設定。
            switch (scaleMode) {
                case ScaleMode.CENTER_CROP:
                    request.centerCrop();
                    break;
                case ScaleMode.FIT_CENTER:
                    request.fitCenter();
                    break;
                default:
                    request.fitCenter();
                    break;
            }

其他的方法與此方法相同,就不在這做詳細說明了。

總結

總結一下,其實主要思路就是在GlobalConfig中選擇使用哪一個圖片載入庫,然後將使用者的所用設定資訊儲存在SingleConfig中,然後在具體的Loader中去實現,本文使用的Glide,也可以增加FrescoLoader,只需要實現ILoader然後實現request()方法去通過DrawableTypeRequest設定就好了。

更多程式碼可以查詢本人GitHub:歡迎閱讀,star點起來。
Glide二次封裝庫原始碼

看一下效果哦:
這裡寫圖片描述

到這裡我們的封裝就結束了,就可以愉快的使用了,歡迎大家提出意見與建議。

使用

在gradle中新增如下配置

compile 'com.libin.imageloader:ImageLoader:1.0.3'

在Application中:

    ImageLoader.init(getApplicationContext());

為了防止oom,加入如下程式碼,清理記憶體:

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);

        ImageLoader.trimMemory(level);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();

        ImageLoader.clearAllMemoryCaches();
    }

混淆

在proguard-rules中新增如下

-dontwarn okio.**

由於具體使用文章較長,具體如何使用詳細API介紹請移步本人下一篇部落格
Glide二次封裝庫的使用

更多程式碼可以查詢本人GitHub:歡迎閱讀,star點起來。
Glide二次封裝庫原始碼

掃碼關注公眾號“偉大程式猿的誕生“,更多幹貨等著你~
掃碼關注公眾號“偉大程式猿的誕生“,更多幹貨等著你~
掃碼關注公眾號“偉大程式猿的誕生“,更多幹貨等著你~