国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

詳解Glide4.0集成及使用注意事項

2019-10-21 21:39:23
字體:
來源:轉載
供稿:網友

Glide 4.0由Google的各種團隊內部使用,4.0被認為是內部穩定的。但外部用戶可能會發現內部尚未發現的問題。因此,將此作為RC發布。如果沒有發現穩定性或API中的重大問題,預計不久之后就會發布非RC版本。

一、集成

1、project gradle

 repositories {    mavenLocal() }

2、app gradle

compile 'com.android.support:support-v4:25.3.1'compile 'com.github.bumptech.glide:glide:4.0.0'annotationProcessor 'com.github.bumptech.glide:compiler:4.0.0'

3、混淆

#glide4.0-keep public class * implements com.bumptech.glide.module.GlideModule-keep public class * extends com.bumptech.glide.AppGlideModule-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { **[] $VALUES; public *;}# for DexGuard only-keepresourcexmlelements manifest/application/meta-data@value=GlideModule# 從glide4.0開始,GifDrawable沒有提供getDecoder()方法,# 需要通過反射獲取gifDecoder字段值,所以需要保持GifFrameLoader和GifState類不被混淆-keep class com.bumptech.glide.load.resource.gif.GifDrawable$GifState{*;}-keep class com.bumptech.glide.load.resource.gif.GifFrameLoader {*;}

4、在4.0中不用像3.X需要在AndroidManifest.xml配置GlideModule,而是通過注解繼承AppGlideModule的子類來配置。

@GlideModulepublic class GlideConfiguration extends AppGlideModule {  @Override  public void applyOptions(Context context, GlideBuilder builder) {    //自定義緩存目錄,磁盤緩存給150M 另外一種設置緩存方式    builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "GlideImgCache", 150 * 1024 * 1024));    //配置圖片緩存格式 默認格式為8888    builder.setDefaultRequestOptions(RequestOptions.formatOf(DecodeFormat.PREFER_ARGB_8888));    ViewTarget.setTagId(R.id.glide_tag_id);  }  /**   * 禁止解析Manifest文件   * 主要針對V3升級到v4的用戶,可以提升初始化速度,避免一些潛在錯誤   * @return   */  @Override  public boolean isManifestParsingEnabled() {    return false;  }}

二、使用注意事項

1、使用GlideApp代替Glide,asBitmap、asGif、asDrawable、asFile都要放到load之前(glide3.7.0都是要在load之后調用)。

public static void loadImg(Context context,String url, ImageView imageView){    GlideApp.with(context)        .asBitmap()        .load(url)        .placeholder(R.drawable.placeholder) //設置資源加載過程中的占位符        .into(imageView);  }

2、占位符.placeholder(R.drawable.placeholder)不能用.9圖,占位圖片和加載的目標圖片會同時顯示,只是目標圖片會先顯示縮略圖,然后顯示正常。fallback和error還沒測試過,有興趣的可以測試看看。

3、加載gif圖時,若調用dontAnimate()移除所有動畫,gif就會加載失敗。

4、計算gif播放一次的動畫時長。

glide 3.7.0你可以這樣獲取動畫時長:

 public void loadGif(Context context,ImageView mIvGif,int url){    Glide.with(context)        .load(url)        .listener(new RequestListener<Integer, GlideDrawable>() {          @Override          public boolean onException(Exception e, Integer model, Target<GlideDrawable> target, boolean isFirstResource) {            return false;          }          @Override          public boolean onResourceReady(GlideDrawable resource, Integer model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {            try {              int duration = 0;              GifDrawable gifDrawable = (GifDrawable) resource;              GifDecoder decoder = gifDrawable.getDecoder();              for (int i = 0; i < gifDrawable.getFrameCount(); i++) {                duration += decoder.getDelay(i);              }              Log.e("Glide3.7.0","gif播放一次動畫時長duration:"+duration);            } catch (Throwable e) {            }            return false;          }        })        .into(new GlideDrawableImageViewTarget(mIvGif, 1));  }

glide4.0中GifDrawable沒有提供getDecoder()方法并且還去掉了decoder這個成員變量。除此之外,glide4.0還去掉了GlideDrawableImageViewTarget類,那我們該如何來計算gif播放一次的時長呢?只能從源碼中找答案了。

(1)尋找decoder

glide3.7.0 GifDrawable中我們可以發現decoder最終于會傳入GifFrameLoader類中并賦值給gifDecoder變量。

//源碼//glide 3.7.0 GifDrawable.java GifDrawable(GifState state) {    if (state == null) {      throw new NullPointerException("GifState must not be null");    }    this.state = state;    this.decoder = new GifDecoder(state.bitmapProvider);    this.paint = new Paint();    decoder.setData(state.gifHeader, state.data);    frameLoader = new GifFrameLoader(state.context, this, decoder, state.targetWidth, state.targetHeight);    frameLoader.setFrameTransformation(state.frameTransformation);  }/*---------------------------------------------------------------------------------------------------*///glide 3.7.0 GifFrameLoader.javaprivate final GifDecoder gifDecoder;//私有屬性public GifFrameLoader(Context context, FrameCallback callback, GifDecoder gifDecoder, int width, int height) {    this(callback, gifDecoder, null,        getRequestBuilder(context, gifDecoder, width, height, Glide.get(context).getBitmapPool())); }  GifFrameLoader(FrameCallback callback, GifDecoder gifDecoder, Handler handler,      GenericRequestBuilder<GifDecoder, GifDecoder, Bitmap, Bitmap> requestBuilder) {    if (handler == null) {      handler = new Handler(Looper.getMainLooper(), new FrameLoaderCallback());    }    this.callback = callback;    //看這里    this.gifDecoder = gifDecoder;    this.handler = handler;    this.requestBuilder = requestBuilder;  }

glide4.0 GifDrawable類的構造中我們可以看到有一個gifDecoder的參數,這個參數的解釋是解碼器用于解碼GIF數據(The decoder to use to decode GIF data)。繼續看這個構造,發現gifDecoder最終也是被傳到GifFrameLoader類中并賦值給gifDecoder變量。所以glide3.7.0中的decoder其實就是4.0中的gifDecoder。

//源碼//glide 4.0 GifDrawable.javaprivate final GifState state;/*  * @param gifDecoder     The decoder to use to decode GIF data.  * @param firstFrame     The decoded and transformed first frame of this GIF.  * @see #setFrameTransformation(com.bumptech.glide.load.Transformation, android.graphics.Bitmap)  */ public GifDrawable(Context context, GifDecoder gifDecoder, BitmapPool bitmapPool,   Transformation<Bitmap> frameTransformation, int targetFrameWidth, int targetFrameHeight,   Bitmap firstFrame) {  this(    new GifState(      bitmapPool,      new GifFrameLoader(        // TODO(b/27524013): Factor out this call to Glide.get()        Glide.get(context),        gifDecoder,        targetFrameWidth,        targetFrameHeight,        frameTransformation,        firstFrame))); }/*---------------------------------------------------------------------------------------------*///glide4.0 GifFrameLoader.javaprivate final GifDecoder gifDecoder;//私有屬性 public GifFrameLoader(   Glide glide,   GifDecoder gifDecoder,   int width,   int height,   Transformation<Bitmap> transformation,   Bitmap firstFrame) {  this(    glide.getBitmapPool(),    Glide.with(glide.getContext()),    gifDecoder,    null /*handler*/,    getRequestBuilder(Glide.with(glide.getContext()), width, height),    transformation,    firstFrame); } @SuppressWarnings("PMD.ConstructorCallsOverridableMethod") GifFrameLoader(   BitmapPool bitmapPool,   RequestManager requestManager,   GifDecoder gifDecoder,   Handler handler,   RequestBuilder<Bitmap> requestBuilder,   Transformation<Bitmap> transformation,   Bitmap firstFrame) {  this.requestManager = requestManager;  if (handler == null) {   handler = new Handler(Looper.getMainLooper(), new FrameLoaderCallback());  }  this.bitmapPool = bitmapPool;  this.handler = handler;  this.requestBuilder = requestBuilder;  //看這里  this.gifDecoder = gifDecoder;  setFrameTransformation(transformation, firstFrame); }

(2)獲取decoder

從上面Glide4.0的GifDrawable構造中可以看到gifDecoder被傳遞到GifFrameLoader中賦值給私有屬性gifDecoder;,而GifFrameLoader又被傳入GifState中并被賦值給它的成員變量frameLoader,那要怎么獲取frameLoader?

從源碼中,可以看到GifDrawable提供了getConstantState()方法來獲取state變量(這個變量的類型就是GifState),但是GifState并沒有get方法獲取frameLoader,frameLoader對象中的gifDecoder也是私有,也沒有提供get方法來獲取,那么我們只能通過反射來獲取了。

//源碼//glide4.0 GifDrawable.javaprivate final GifState state; @Override public ConstantState getConstantState() {  return state; } static class GifState extends ConstantState {  static final int GRAVITY = Gravity.FILL;  final BitmapPool bitmapPool;  final GifFrameLoader frameLoader;  public GifState(BitmapPool bitmapPool, GifFrameLoader frameLoader) {   this.bitmapPool = bitmapPool;   this.frameLoader = frameLoader;  }  @Override  public Drawable newDrawable(Resources res) {   return newDrawable();  }  @Override  public Drawable newDrawable() {   return new GifDrawable(this);  }  @Override  public int getChangingConfigurations() {   return 0;  } }

通過反射來獲取獲取decoder

.listener(new RequestListener<GifDrawable>() {          @Override          public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {            return false;          }          @Override          public boolean onResourceReady(GifDrawable gifDrawable, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {            try {              int duration = 0;              // 計算動畫時長              //GifDecoder decoder = gifDrawable.getDecoder();//4.0開始沒有這個方法了              Drawable.ConstantState state = gifDrawable.getConstantState();              if(state!=null){                //不能混淆GifFrameLoader和GifState類                Object gifFrameLoader = getValue(state,"frameLoader");                if(gifFrameLoader!=null){                  Object decoder = getValue(gifFrameLoader,"gifDecoder");                  if(decoder!=null && decoder instanceof GifDecoder){                    for (int i = 0; i < gifDrawable.getFrameCount(); i++) {                      duration += ((GifDecoder) decoder).getDelay(i);                    }                  }                }                Log.e("Glide4.0","gif播放動畫時長duration:"+duration);              }            } catch (Throwable e) {            }            return false;          }        })/*---------------------------------------------------------------------------------------------*//**   * 通過字段名從對象或對象的父類中得到字段的值   * @param object 對象實例   * @param fieldName 字段名   * @return 字段對應的值   * @throws Exception   */  public static Object getValue(Object object, String fieldName) throws Exception {    if (object == null) {      return null;    }    if (TextUtils.isEmpty(fieldName)) {      return null;    }    Field field = null;    Class<?> clazz = object.getClass();    for (; clazz != Object.class; clazz = clazz.getSuperclass()) {      try {        field = clazz.getDeclaredField(fieldName);        field.setAccessible(true);        return field.get(object);      } catch (Exception e) {        //這里甚么都不要做!并且這里的異常必須這樣寫,不能拋出去。        //如果這里的異常打印或者往外拋,則就不會執行clazz = clazz.getSuperclass(),最后就不會進入到父類中了      }    }    return null;  }

(3)設置gif循環播放次數

glide4.0中沒有GlideDrawableImageViewTarget類,那么怎么設置循環播放次數呢?

從glide3.7.0源碼可以發現GlideDrawableImageViewTarget是通過GlideDrawable的setLoopCount方法來設置循環播放次數的,查看setLoopCount具體實現地方是在GifDrawable,所以這里調用的其實是GifDrawable的setLoopCount方法。glide4.0中沒有GlideDrawable類和GlideDrawableImageViewTarget類,但是仍然有GifDrawable類,并且onResourceReady方法中第一個參數就是GifDrawable,所以可以直接調用GifDrawable的setLoopCount(loopCount)來設置播放次數。

//源碼//3.7.0 GlideDrawableImageViewTarget.java public GlideDrawableImageViewTarget(ImageView view, int maxLoopCount) {    super(view);    this.maxLoopCount = maxLoopCount; }  @Override  public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {    if (!resource.isAnimated()) {      //TODO: Try to generalize this to other sizes/shapes.      // This is a dirty hack that tries to make loading square thumbnails and then square full images less costly      // by forcing both the smaller thumb and the larger version to have exactly the same intrinsic dimensions.      // If a drawable is replaced in an ImageView by another drawable with different intrinsic dimensions,      // the ImageView requests a layout. Scrolling rapidly while replacing thumbs with larger images triggers      // lots of these calls and causes significant amounts of jank.      float viewRatio = view.getWidth() / (float) view.getHeight();      float drawableRatio = resource.getIntrinsicWidth() / (float) resource.getIntrinsicHeight();      if (Math.abs(viewRatio - 1f) <= SQUARE_RATIO_MARGIN          && Math.abs(drawableRatio - 1f) <= SQUARE_RATIO_MARGIN) {        resource = new SquaringDrawable(resource, view.getWidth());      }    }    super.onResourceReady(resource, animation);    this.resource = resource;    //********看這里******    //android studio可以通過快捷鍵Ctrl+Alt+B查看其實現    resource.setLoopCount(maxLoopCount);    resource.start();  }

glide4.0 計算gif一次播放時長代碼:

  public static void loadGifImg(Context context,String url, ImageView imageView){    GlideApp.with(context)        .asGif()        .load(url)        .placeholder(R.drawable.placeholder)        .fallback(R.drawable.fallback)        .listener(new RequestListener<GifDrawable>() {          @Override          public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {            return false;          }          @Override          public boolean onResourceReady(GifDrawable gifDrawable, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {            try {              //設置循環播放次數為1次              gifDrawable.setLoopCount(1);              // 計算動畫時長              int duration = 0;              //GifDecoder decoder = gifDrawable.getDecoder();//4.0開始沒有這個方法了              Drawable.ConstantState state = gifDrawable.getConstantState();              if(state!=null){                //不能混淆GifFrameLoader和GifState類                Object gifFrameLoader = getValue(state,"frameLoader");                if(gifFrameLoader!=null){                  Object decoder = getValue(gifFrameLoader,"gifDecoder");                  if(decoder!=null && decoder instanceof GifDecoder){                    for (int i = 0; i < gifDrawable.getFrameCount(); i++) {                      duration += ((GifDecoder) decoder).getDelay(i);                    }                  }                }                Log.e("Glide4.0","gif播放一次動畫時長duration:"+duration);              }            } catch (Throwable e) {            }            return false;          }        })        .into(imageView);  }

注意:因為用了反射獲取decoder,所以不能混淆GifFrameLoader和GifState類

5、設置淡入淡出動畫

glide3.7.0

Glide.with(context)        .load(url)        .crossFade(100) //系統漸變動畫        .placeholder(R.drawable.placeholder)        .fallback(R.drawable.fallback)         .diskCacheStrategy(DiskCacheStrategy.ALL)         .into(imageView);

glide4.0

GlideApp.with(context)        .load(url)        .transition(DrawableTransitionOptions.withCrossFade(100))//淡入淡出100m        .placeholder(R.drawable.placeholder)        .fallback(R.drawable.fallback)         .diskCacheStrategy(DiskCacheStrategy.ALL)        .into(imageView);

6、緩存策略

glide3.7.0

//DiskCacheStrategy.SOURCE:緩存原始數據//DiskCacheStrategy.RESULT:緩存變換(如縮放、裁剪等)后的資源數據//DiskCacheStrategy.NONE:什么都不緩存//DiskCacheStrategy.ALL:緩存SOURC和RESULT//默認采用DiskCacheStrategy.RESULT策略,對于download only操作要使用DiskCacheStrategy.SOURCE

glide4.0

//DiskCacheStrategy.ALL 使用DATA和RESOURCE緩存遠程數據,僅使用RESOURCE來緩存本地數據。// DiskCacheStrategy.NONE 不使用磁盤緩存// DiskCacheStrategy.DATA 在資源解碼前就將原始數據寫入磁盤緩存// DiskCacheStrategy.RESOURCE 在資源解碼后將數據寫入磁盤緩存,即經過縮放等轉換后的圖片資源。// DiskCacheStrategy.AUTOMATIC 根據原始圖片數據和資源編碼策略來自動選擇磁盤緩存策略。//默認采用DiskCacheStrategy.AUTOMATIC策略/*-------------------------------------------------------------------------------*///源碼 RequestOptions.javaprivate DiskCacheStrategy diskCacheStrategy = DiskCacheStrategy.AUTOMATIC;

7、占位符、錯誤圖片設置

glide4.0 若into中設置的是target,占位符(placeholder、error)需要在回調中再次設置,否則無效。

 public static void loadImg(String url, ImageView imageView) {    //into中用Target,占位符(placeholder、error)需要在回調中設置    GlideApp.with(FanhuanApplication.getInstance().getApplication())        .asBitmap()        .load(url)        .placeholder(drawbleId) //設置資源加載過程中的占位符        .fallback(drawbleId)        .error(drawbleId)        .diskCacheStrategy(DiskCacheStrategy.ALL)        .into(new SimpleTarget<Bitmap>() {          @Override          public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {            imageView.setImageBitmap(resource);                   }          @Override          public void onLoadFailed(@Nullable Drawable errorDrawable) {            super.onLoadFailed(errorDrawable);             if(errorDrawable!=null){              imageView.setImageDrawable(errorDrawable);            }                   }          @Override          public void onLoadStarted(@Nullable Drawable placeholder) {            super.onLoadStarted(placeholder);            if(placeholder!=null){              imageView.setImageDrawable(placeholder);            }          }        });  }

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 新沂市| 德安县| 建平县| 丹阳市| 咸丰县| 浮梁县| 丽江市| 盐亭县| 永修县| 扬中市| 金门县| 香港 | 蚌埠市| 秀山| 安西县| 延长县| 马关县| 铅山县| 珲春市| 汪清县| 宜宾县| 宜丰县| 射洪县| 鹿泉市| 上杭县| 绵竹市| 双江| 辛集市| 东乡| 翁源县| 岑溪市| 洛隆县| 宜良县| 合阳县| 武功县| 怀来县| 连云港市| 石渠县| 南投县| 泰兴市| 杭锦旗|