关于glide加载图片时,如何显示进度?
首先,glide是没有接口可以进行进度监听的,所以要进行进一步的代码编写。
相关文章 glide加载https报错
代码地址在文末
环境
win10
glide4+
androidstudio4.2.2
思考:
(1)如何获取glide请求时的数据
(2)请求数据如何计算
带着这些问题,开始发车:
生成GlideApp对象
首先,需要通过配置,生成GlideApp对象。
(一)gradle配置:
implementation "com.github.bumptech.glide:okhttp3-integration:4.9.0"
implementation 'com.github.bumptech.glide:glide:4.9.0'
kapt 'com.github.bumptech.glide:compiler:4.9.0'
(二)GlideModule文件的编写
@GlideModule
public final class GlideCache extends AppGlideModule {
}
(三)manifest文件的配置
在application标签内,配置以下代码,注意包名路径与实际项目中对应。
<meta-data
android:name="com.example.ktdemo.glide.GlideCache"
android:value="AppGlideModule" />
然后点击编译按钮,即可生成GlideApp对象了。后续操作都是在GlideApp对象中执行。
进度回调实现
要进行进度回调,首先明确一个,就是替换原来glide请求过程中的请求对象,glide请求底层是基于okhttp实现的,可以直接从这方面入手。
(一)替换网络返回时的对象
从拦截器入手,添加一个拦截器,并且捕获到ResponseBody 对象后进行处理。
重写GlideModule中的registerComponents方法,替换请求对象。
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
OkHttpClient.Builder builder = GlideUnsafeOkHttpClient.getUnsafeOkHttpClient();
builder.addInterceptor(new GlideProgressInterceptor());
OkHttpClient okHttpClient = builder.build();
registry.replace(GlideUrl.class, InputStream.class, new GlideOkHttpGlideUrlLoader.Factory(okHttpClient));
}
public class GlideProgressInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
String url = request.url().toString();
ResponseBody responseBody = response.body();
Response newResponse = response.newBuilder().body(
new GlideProgressResponseBody(url, responseBody)).build();
return newResponse;
}
}
最核心的代码
public class GlideProgressResponseBody extends ResponseBody {
private static final String TAG = "ProgressResponseBody";
private BufferedSource mBufferedSource;
private ResponseBody mResponseBody;
// private GlideProgressListener mGlideProgressListener;
private String mUrl;
public GlideProgressResponseBody(String url, ResponseBody responseBody) {
mUrl = url;
mResponseBody = responseBody;
// mGlideProgressListener = GlideProgressInterceptor.getListenerMap().get(url);
}
@Nullable
@Override
public MediaType contentType() {
return mResponseBody.contentType();
}
@Override
public long contentLength() {
return mResponseBody.contentLength();
}
@Override
public BufferedSource source() {
if (mBufferedSource == null) {
mBufferedSource = Okio.buffer(new ProgressSource(mResponseBody.source()));
}
return mBufferedSource;
}
private class ProgressSource extends ForwardingSource {
private long mTotalBytesRead;
private int mCurrentProgress;
public ProgressSource(Source delegate) {
super(delegate);
}
@Override
public long read(Buffer sink, long byteCount) throws IOException {
long bytesRead = super.read(sink, byteCount);
long fullLength = mResponseBody.contentLength();
if (bytesRead == -1) {
mTotalBytesRead = fullLength;
} else {
mTotalBytesRead += bytesRead;
}
int progress = (int) (100f * mTotalBytesRead / fullLength);
Log.e(TAG, "download url is: " + mUrl + " progress is " + progress);
GlideProgressManager.getInstance().notifyProgress(mUrl, progress, (mTotalBytesRead == fullLength));
// if ((mGlideProgressListener != null) && (progress != mCurrentProgress)) {
// mGlideProgressListener.onProgress(progress);
//
// }
//
// if ((mGlideProgressListener != null) && (mTotalBytesRead == fullLength)) {
// mGlideProgressListener = null;
// }
mCurrentProgress = progress;
return bytesRead;
}
}
}
上面代码中,可以看到,我们对进度的数据处理,都是基于一个继承ResponseBody的自定义返回对象进行的。而对外,仅仅是添加了一个拦截器而已。
至此,核心代码都已经讲完了。
调用
下面代码只是实例,实际使用中,需要注意监听对象的及时释放,避免造成内存泄漏。
val imgUrl = "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png"
GlideProgressManager.getInstance().setGlideProgressListener(object :GlideProgressListener{
override fun onProgress(url: String?, progress: Int, isFinish: Boolean) {
Log.d("glide", "glide url:$url progress:$progress isFinish:$isFinish")
}
})
GlideApp.with(this).asBitmap().load(imgUrl).into(object : SimpleTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
Log.d("glide", "glide onResourceReady")
}
})
可能遇到的坑
kapt编译时报错,这个时候,需要检查gradle的版本号。实测目前compileSdkVersion为31的情况下,kapt会报错。修改为了30后可用。
that's all-----------------------------------------------------