Glide 设置下载进度

package com.base.common.glide

import com.bumptech.glide.load.Options
import com.bumptech.glide.load.model.*
import com.bumptech.glide.load.model.ModelLoader.LoadData
import java.io.InputStream
import okhttp3.OkHttpClient


class OkHttpGlideUrlLoader : ModelLoaderFactory<GlideUrl, InputStream>,
    ModelLoader<GlideUrl, InputStream> {
    private val client: OkHttpClient = OkHttpClient.Builder()
        .addInterceptor(ProgressInterceptor())
        .build()
    override fun buildLoadData(
        model: GlideUrl,
        width: Int,
        height: Int,
        options: Options
    ): LoadData<InputStream>? {
        return LoadData(model, OkHttpStreamFetcher(client, model))
    }

    override fun handles(model: GlideUrl): Boolean {
        return true
    }

    override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader<GlideUrl, InputStream> {
        return OkHttpGlideUrlLoader()
    }

    override fun teardown() {

    }
}
package com.base.common.glide

import android.content.Context
import com.bumptech.glide.Glide
import com.bumptech.glide.GlideBuilder
import com.bumptech.glide.Registry
import com.bumptech.glide.annotation.GlideModule

import com.bumptech.glide.module.AppGlideModule
import com.bumptech.glide.load.model.GlideUrl

import java.io.InputStream
import okhttp3.OkHttpClient





@GlideModule
class OkHttpLibraryGlideModule : AppGlideModule() {

    override fun registerComponents(
        context: Context, glide: Glide, registry: Registry
    ) {
        registry.replace(GlideUrl::class.java, InputStream::class.java,OkHttpGlideUrlLoader())
    }
    override fun applyOptions(context: Context, builder: GlideBuilder) {

    }
}

```kotlin
package com.base.common.glide

import android.os.Build
import android.util.Log
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.HttpException
import com.bumptech.glide.load.data.DataFetcher
import okhttp3.Call
import okhttp3.Response
import java.io.IOException
import java.io.InputStream
import okhttp3.ResponseBody

import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.util.Synthetic
import okhttp3.Request
import java.lang.ClassCastException

import com.bumptech.glide.util.ContentLengthInputStream
import com.bumptech.glide.util.Preconditions


class OkHttpStreamFetcher(client: Call.Factory, url: GlideUrl) : DataFetcher<InputStream>,
    okhttp3.Callback {
    companion object{
        private const val TAG = "OkHttpFetcher"
    }
    private val client: Call.Factory? = client
    private val url: GlideUrl? = url

    @Synthetic
    var stream: InputStream? = null

    @Synthetic
    var responseBody: ResponseBody? = null

    private var call: Call? = null

    private var callback: DataFetcher.DataCallback<in InputStream>? = null

    override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
        val requestBuilder: Request.Builder = Request.Builder().url(url!!.toStringUrl())
        for ((key, value) in url.headers) {
            requestBuilder.addHeader(key, value)
        }
        val request: Request = requestBuilder.build()
        this.callback = callback
        call = client?.newCall(request)
        if (Build.VERSION.SDK_INT !== Build.VERSION_CODES.O) {
            call!!.enqueue(this)
        } else {
            try {
                // Calling execute instead of enqueue is a workaround for #2355, where okhttp throws a
                // ClassCastException on O.
                onResponse(call!!, call!!.execute())
            } catch (e: IOException) {
                onFailure(call!!, e)
            } catch (e: ClassCastException) {
                // It's not clear that this catch is necessary, the error may only occur even on O if
                // enqueue is used.
                onFailure(call!!, IOException("Workaround for framework bug on O", e))
            }
        }
    }

    override fun cleanup() {
        try {
            if (stream != null) {
                stream!!.close()
            }
        } catch (e: IOException) {
            // Ignored
        }
        if (responseBody != null) {
            responseBody!!.close()
        }
        callback = null
    }

    override fun cancel() {
        try {
            if (stream != null) {
                stream!!.close()
            }
        } catch (e: IOException) {
            // Ignored
        }
        if (responseBody != null) {
            responseBody!!.close()
        }
        callback = null
    }

    override fun getDataClass(): Class<InputStream> {
        return InputStream::class.java
    }

    override fun getDataSource(): DataSource {
        return DataSource.REMOTE
    }

    override fun onFailure(call: Call, e: IOException) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "OkHttp failed to obtain result", e);
        }
        callback!!.onLoadFailed(e);
    }

    override fun onResponse(call: Call, response: Response) {
        responseBody = response.body()
        if (response.isSuccessful) {
            val contentLength: Long = Preconditions.checkNotNull(responseBody).contentLength()
            stream = ContentLengthInputStream.obtain(responseBody!!.byteStream(), contentLength)
            callback!!.onDataReady(stream)
        } else {
            callback!!.onLoadFailed(HttpException(response.message(), response.code()))
        }
    }
}

```kotlin
package com.base.common.glide

import okhttp3.ResponseBody

import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response

open class ProgressInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request: Request = chain.request()
        val response: Response = chain.proceed(request)
        val url: String = request.url().toString()
        val body: ResponseBody? = response.body()
        return response.newBuilder().body(ProgressResponseBody(url, body!!)).build()
    }

    companion object {
        val LISTENER_MAP: MutableMap<String, ProgressListener> = HashMap()

        //入注册下载监听
        fun addListener(url: String, listener: ProgressListener) {
            LISTENER_MAP[url] = listener
        }

        //取消注册下载监听
        fun removeListener(url: String) {
            LISTENER_MAP.remove(url)
        }
    }
}
package com.base.common.glide

interface ProgressListener {
    fun onProgress(progress: Int)
}
package com.base.common.glide

import androidx.annotation.Nullable
import okhttp3.MediaType
import okhttp3.ResponseBody
import okio.*

class ProgressResponseBody(url: String?, private val responseBody: ResponseBody) :
    ResponseBody() {
    private var bufferedSource: BufferedSource? = null
    private var listener: ProgressListener? = ProgressInterceptor.LISTENER_MAP[url]

    @Nullable
    override fun contentType(): MediaType? {
        return responseBody.contentType()
    }

    override fun contentLength(): Long {
        return responseBody.contentLength()
    }

    override fun source(): BufferedSource {
        if (bufferedSource == null) {
            bufferedSource = Okio.buffer(ProgressSource(responseBody.source()))
        }
        return bufferedSource!!
    }

    private inner class ProgressSource internal constructor(source: Source?) :
        ForwardingSource(source) {
        var totalBytesRead: Long = 0
        var currentProgress = 0

        override fun read(sink: Buffer, byteCount: Long): Long {
            val bytesRead = super.read(sink, byteCount)
            val fullLength = responseBody.contentLength()
            if (bytesRead == -1L) {
                totalBytesRead = fullLength
            } else {
                totalBytesRead += bytesRead
            }
            val progress = (100f * totalBytesRead / fullLength).toInt()
            if (listener != null && progress != currentProgress) {
                listener!!.onProgress(progress)
            }
            if (listener != null && totalBytesRead == fullLength) {
                listener = null
            }
            currentProgress = progress
            return bytesRead
        }
    }

    companion object {
        private const val TAG = "XGlide"
    }

}
<meta-data android:name="om.base.common.OkHttpLibraryGlideModule"
    android:value="AppGlideModule"/>
plugins {
    id 'kotlin-kapt'
}

api "com.github.bumptech.glide:glide:4.11.0"
kapt 'com.github.bumptech.glide:compiler:4.11.0'
  GlideApp.with(this)
            .asDrawable()
            .load("https://img1.baidu.com/it/u=3802863026,3009062800&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500")
            .diskCacheStrategy(DiskCacheStrategy.NONE)
            // 设置缓存之后只会有一次进度,所以这里去除缓存
            .skipMemoryCache(true)
            .into(object: CustomTarget<Drawable?>(){
                override fun onResourceReady(
                    resource: Drawable,
                    transition: Transition<in Drawable?>?
                ) {

                }

                override fun onLoadCleared(placeholder: Drawable?) {

                }
            })

原文连接:https://www.jianshu.com/p/61a0761e6e81

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
IntroductionProgressManager 一行代码即可监听 App 中所有网络链接的上传以及下载进度,包括 Glide 的图片加载进度,实现原理类似 EventBus,你可在 App 中的任何地方,将多个监听器,以 Url 地址作为标识符,注册到本框架,当此 Url 地址存在下载或者上传的动作时,框架会主动调用所有使用此 Url 地址注册过的监听器,达到多个模块的同步更新.框架的构思和实现可以看这篇文章Feature使用简单,只需一行代码即可实现进度监听.多平台支持,支持 Okhttp , Retrofit , Glide ,使用 Okhttp 原生 Api ,不存在兼容问题.低耦合,实际请求端和进度接收端并不存在直接或间接的关联关系,即可以在 App 任何地方接收进度信息.侵入性低,使用本框架你并不需要更改之前进行上传或下载的代码,即使用或不使用本框架并不会影响到原有的代码.多端同步,同一个数据源的上传或下载进度可以指定多个不同的接收端,少去了使用 EventBus 实现多个端口同步更新进度.自动管理监听器,少去了手动注销监听器的烦恼.默认运行在主线层,少去了切换线程的烦恼.轻量级框架,不包含任何三方库,体积极小.Download compile 'me.jessyan:progressmanager:1.2.5'UsageStep 1 // 构建 OkHttpClient 时,将 OkHttpClient.Builder() 传入 with() 方法,进行初始化配置  OkHttpClient = ProgressManager.getInstance().with(new OkHttpClient.Builder())                 .build();Step 2 // Glide 下载监听  ProgressManager.getInstance().addResponseListener(IMAGE_URL, getGlideListener()); // Okhttp/Retofit 下载监听  ProgressManager.getInstance().addResponseListener(DOWNLOAD_URL, getDownloadListener()); // Okhttp/Retofit 上传监听  ProgressManager.getInstance().addRequestLisenter(UPLOAD_URL, getUploadListener());ProGuard -keep class me.jessyan.progressmanager.** { *; }  -keep interface me.jessyan.progressmanager.** { *; }About MeEmail: jess.yan.effort@gmail.comHome: http://jessyan.me掘金: https://gold.xitu.io/user/57a9dbd9165abd0061714613简书: http://www.jianshu.com/u/1d0c0bc634db

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值