成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Android基于Glidev4.x如何實(shí)現(xiàn)圖片加載進(jìn)度監(jiān)聽-創(chuàng)新互聯(lián)

這篇文章主要介紹Android基于Glide v4.x如何實(shí)現(xiàn)圖片加載進(jìn)度監(jiān)聽,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

創(chuàng)新互聯(lián)建站是一家專注于成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)與策劃設(shè)計(jì),湞江網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)建站做網(wǎng)站,專注于網(wǎng)站建設(shè)十余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:湞江等地區(qū)。湞江做網(wǎng)站價(jià)格咨詢:18982081108

Glide是一款優(yōu)秀的圖片加載框架,簡單的配置便可以使用起來,為開發(fā)者省下了很多的功夫。不過,它沒有提供其加載圖片進(jìn)度的api,對(duì)于這樣的需求,實(shí)現(xiàn)起來還真頗費(fèi)一番周折。

嘗試

遇到這個(gè)需求,第一反應(yīng)是網(wǎng)上肯定有人實(shí)現(xiàn)過,不妨借鑒一下別人的經(jīng)驗(yàn)。

Glide加載圖片實(shí)現(xiàn)進(jìn)度條效果

可惜,這個(gè)實(shí)現(xiàn)是基于3.7版本的,4.0版本以上的glide改動(dòng)比較大,using函數(shù)已經(jīng)被移除了

using()
The using() API was removed in Glide 4 to encourage users to register their components once with a AppGlideModule to avoid object re-use. Rather than creating a new ModelLoader each time you load an image, you register it once in an AppGlideModule and let Glide inspect your model (the object you pass to load()) to figure out when to use your registered ModelLoader.
To make sure you only use your ModelLoader for certain models, implement handles() as shown above to inspect each model and return true only if your ModelLoader should be used.

思考

又要用最新的版本又希望給其增加功能,魚與熊掌不可兼得?“貪新厭舊”的我怎會(huì)輕易放棄。我對(duì)加載圖片進(jìn)度的需求再理了一遍,發(fā)現(xiàn)可以用其他思路簡化一下:

  • 加載圖片分為加載本地圖片和網(wǎng)絡(luò)圖片

  • 加載本地圖片速度很快,主要耗時(shí)在圖片解碼的工作,如果圖片已經(jīng)在內(nèi)存中,解碼的步驟也省去了

  • 加載網(wǎng)絡(luò)圖片主要時(shí)間耗在下載圖片數(shù)據(jù)過程中

所以,能監(jiān)聽到圖片的下載進(jìn)度就大概是圖片的加載進(jìn)度了。那難道要先下載圖片再交給glide去加載?不用,glide支持整合其他網(wǎng)絡(luò)模塊,例如OkHttp,并且如果我們?cè)敢獾脑?,也可以利用其接口?shí)現(xiàn)自己的網(wǎng)絡(luò)加載模塊。

glide官方倉庫提供了OkHttp的整合模塊,于是乎我去這些代碼了尋找一下突破口。

突破

OkHttp模塊是非常簡單的,只有4個(gè)文件,并且文件都不長

首先,用過glide的都知道,繼承GlideModule的類是用于設(shè)置glide的配置信息和加載模塊的,在OkHttpGlideModule里,向系統(tǒng)注冊(cè)了一個(gè)用于加載GlideUrl類型的組件,簡單的可以理解為加載網(wǎng)絡(luò)圖片的組件。

public class OkHttpGlideModule implements GlideModule {
  public OkHttpGlideModule() {
  }

  public void applyOptions(Context context, GlideBuilder builder) {
  }

  public void registerComponents(Context context, Glide glide, Registry registry) {
    registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory());
  }
}

OkHttpLoader文件也很簡單,實(shí)現(xiàn)了ModelLoader接口,這里ModelLoader是glide的抽象的資源loader的表示,例如這里,就是說加載GlideUrl的model,返回InputStream,即圖片的輸入流。關(guān)于Glide的loadData、model、fetch的詳細(xì)介紹,可以查看 官方文檔

OkHttpLoader的最終目的,也就是返回了一個(gè)LoadData對(duì)象。現(xiàn)在情況明確了,glide框架就是利用這個(gè)LoadData對(duì)象得到圖片的輸入流,從而下載圖片并經(jīng)過一系列的解碼,裁剪,緩存等操作,最后加載出來的。LoadData的參數(shù)有一個(gè)OkHttpStreamFetcher,從名字看來,這里一定就是下載圖片的地方了,我們繼續(xù)看下去。

public class OkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> {
  private final okhttp3.Call.Factory client;

  public OkHttpUrlLoader(okhttp3.Call.Factory client) {
    this.client = client;
  }

  public boolean handles(GlideUrl url) {
    return true;
  }

  public LoadData<InputStream> buildLoadData(GlideUrl model, int width, int height, Options options) {
    //返回LoadData對(duì)象,泛型為InputStream
    return new LoadData(model, new OkHttpStreamFetcher(this.client, model));
  }

  public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
    private static volatile okhttp3.Call.Factory internalClient;
    private okhttp3.Call.Factory client;

    private static okhttp3.Call.Factory getInternalClient() {
      if(internalClient == null) {
        Class var0 = OkHttpUrlLoader.Factory.class;
        synchronized(OkHttpUrlLoader.Factory.class) {
          if(internalClient == null) {
            internalClient = new OkHttpClient();
          }
        }
      }

      return internalClient;
    }

    public Factory() {
      this(getInternalClient());
    }

    public Factory(okhttp3.Call.Factory client) {
      this.client = client;
    }

    public ModelLoader<GlideUrl, InputStream> build(MultiModelLoaderFactory multiFactory) {
      return new OkHttpUrlLoader(this.client);
    }

    public void teardown() {
    }
  }
}

可以看到,所有的重點(diǎn)都在loadData函數(shù)里面了,用過OkHttp的同學(xué),有沒有覺得好簡單?哈哈。

這里直接得到圖片的InputStream然后通過回調(diào)函數(shù)callback.onDataReady()返回了

問題來了,callback的glide框架里傳過來的,我們并不能控制,我嘗試找了一下調(diào)用loadData的地方,結(jié)果沒有找到。怎么辦?看最終的實(shí)現(xiàn)吧。

public class OkHttpStreamFetcher implements DataFetcher<InputStream> {
  private static final String TAG = "OkHttpFetcher";
  private final Factory client;
  private final GlideUrl url;
  InputStream stream;
  ResponseBody responseBody;
  private volatile Call call;

  public OkHttpStreamFetcher(Factory client, GlideUrl url) {
    this.client = client;
    this.url = url;
  }

  public void loadData(Priority priority, final DataCallback<? super InputStream> callback) {
    Builder requestBuilder = (new Builder()).url(this.url.toStringUrl());
    Iterator request = this.url.getHeaders().entrySet().iterator();

    while(request.hasNext()) {
      Entry headerEntry = (Entry)request.next();
      String key = (String)headerEntry.getKey();
      requestBuilder.addHeader(key, (String)headerEntry.getValue());
    }

    Request request1 = requestBuilder.build();
    this.call = this.client.newCall(request1);
    this.call.enqueue(new Callback() {
      public void onFailure(Call call, IOException e) {
        if(Log.isLoggable("OkHttpFetcher", 3)) {
          Log.d("OkHttpFetcher", "OkHttp failed to obtain result", e);
        }

        callback.onLoadFailed(e);
      }

      public void onResponse(Call call, Response response) throws IOException {
        OkHttpStreamFetcher.this.responseBody = response.body();
        if(response.isSuccessful()) {
          long contentLength = OkHttpStreamFetcher.this.responseBody.contentLength();
          OkHttpStreamFetcher.this.stream = ContentLengthInputStream.obtain(OkHttpStreamFetcher.this.responseBody.byteStream(), contentLength);
          callback.onDataReady(OkHttpStreamFetcher.this.stream);
        } else {
          callback.onLoadFailed(new HttpException(response.message(), response.code()));
        }

      }
    });
  }

  public void cleanup() {
    try {
      if(this.stream != null) {
        this.stream.close();
      }
    } catch (IOException var2) {
      ;
    }

    if(this.responseBody != null) {
      this.responseBody.close();
    }

  }

  public void cancel() {
    Call local = this.call;
    if(local != null) {
      local.cancel();
    }

  }

  public Class<InputStream> getDataClass() {
    return InputStream.class;
  }

  public DataSource getDataSource() {
    return DataSource.REMOTE;
  }
}

實(shí)現(xiàn)

在loadData函數(shù)里,有這樣一句代碼

復(fù)制代碼 代碼如下:


OkHttpStreamFetcher.this.stream = ContentLengthInputStream.obtain(OkHttpStreamFetcher.this.responseBody.byteStream(), contentLength);

ContentLengthInputStream是glide的工具類,用來讀取輸入流的,點(diǎn)進(jìn)去看看,發(fā)現(xiàn)有幾個(gè)read方法

  public synchronized int read() throws IOException {
    int value = super.read();
    this.checkReadSoFarOrThrow(value >= 0?1:-1);
    return value;
  }

  public int read(byte[] buffer) throws IOException {
    return this.read(buffer, 0, buffer.length);
  }

  public synchronized int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
    return this.checkReadSoFarOrThrow(super.read(buffer, byteOffset, byteCount));
  }

所以,我的解決方法就是在這里計(jì)算下載進(jìn)度和進(jìn)行進(jìn)度的報(bào)告的,把這個(gè)類從源碼里拷貝出來,替換掉OkHttp模塊里面的ContentLengthInputStream,并在這插入自己的下載進(jìn)度邏輯就行了。

具體的代碼實(shí)現(xiàn)就不貼出來了,寫個(gè)大概的思路:

下載圖片的時(shí)候傳入圖片進(jìn)度監(jiān)聽,用集合容器,例如map保存監(jiān)聽的實(shí)例,key為url,下載過程中計(jì)算下載進(jìn)度后通過url找到對(duì)應(yīng)的回調(diào)返回進(jìn)度,圖片加載完畢后將回調(diào)從集合了移除(glide提供了圖片加載完畢的回調(diào))。

ok,就這樣,有不合理的地方歡迎指出,又更好更優(yōu)雅的實(shí)現(xiàn)方式請(qǐng)不吝指教。

以上是“Android基于Glide v4.x如何實(shí)現(xiàn)圖片加載進(jìn)度監(jiān)聽”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

分享名稱:Android基于Glidev4.x如何實(shí)現(xiàn)圖片加載進(jìn)度監(jiān)聽-創(chuàng)新互聯(lián)
鏈接地址:http://jinyejixie.com/article40/jghho.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計(jì)公司用戶體驗(yàn)、網(wǎng)站策劃、網(wǎng)站內(nèi)鏈、網(wǎng)站改版、關(guān)鍵詞優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)
澳门| 罗源县| 龙海市| 闽侯县| 平乐县| 连江县| 壤塘县| 阳泉市| 浠水县| 赫章县| 华坪县| 湟源县| 安岳县| 荔浦县| 利津县| 句容市| 湖州市| 行唐县| 和硕县| 盐边县| 浠水县| 临漳县| 朝阳市| 高雄县| 古浪县| 蒙阴县| 邯郸市| 台山市| 克山县| 丹棱县| 和田市| 社旗县| 白城市| 合阳县| 和顺县| 莲花县| 濮阳市| 新邵县| 新密市| 天等县| 涪陵区|