关于安卓glide加载显示进度

简介: 安卓glide加载显示进度

关于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-----------------------------------------------------

目录
相关文章
|
4月前
|
Java Android开发
Android面试题经典之Glide取消加载以及线程池优化
Glide通过生命周期管理在`onStop`时暂停请求,`onDestroy`时取消请求,减少资源浪费。在`EngineJob`和`DecodeJob`中使用`cancel`方法标记任务并中断数据获取。当网络请求被取消时,`HttpUrlFetcher`的`cancel`方法设置标志,之后的数据获取会返回`null`,中断加载流程。Glide还使用定制的线程池,如AnimationExecutor、diskCacheExecutor、sourceExecutor和newUnlimitedSourceExecutor,其中某些禁止网络访问,并根据CPU核心数动态调整线程数。
135 2
|
24天前
|
Android开发 UED
Android 中加载 Gif 动画
【10月更文挑战第20天】加载 Gif 动画是 Android 开发中的一项重要技能。通过使用第三方库或自定义实现,可以方便地在应用中展示生动的 Gif 动画。在实际应用中,需要根据具体情况进行合理选择和优化,以确保用户体验和性能的平衡。可以通过不断的实践和探索,进一步掌握在 Android 中加载 Gif 动画的技巧和方法,为开发高质量的 Android 应用提供支持。
|
3月前
|
存储 缓存 Java
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
45 0
|
3月前
|
Java Android开发 Kotlin
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
36 0
|
5月前
|
XML API 开发工具
Android Bitmap 加载与像素操作
Android Bitmap 加载与像素操作
48 2
|
4月前
|
缓存 编解码 安全
Android经典面试题之Glide的缓存大揭秘
Glide缓存机制包括内存和硬盘缓存。内存缓存使用弱引用的ActiveResources和LRU策略,硬盘缓存利用DiskLruCache。Engine.load方法首先尝试从内存和弱引用池加载,然后从LRU缓存中加载图片,增加引用计数并移出LRU。若缓存未命中,启动新任务或加入现有任务。内存大小根据设备内存动态计算,限制在0.4以下。DiskLruCache使用自定义读写锁,保证并发安全,写操作通过锁池管理,确保高效。
121 0
|
6月前
|
Android开发
Android中Glide加载Https图片失败的解决方案
Android中Glide加载Https图片失败的解决方案
454 1
|
6月前
|
编解码 调度 Android开发
Android音频框架之一 详解audioPolicy流程及HAL驱动加载与配置
Android音频框架之一 详解audioPolicy流程及HAL驱动加载与配置
641 0
|
6月前
|
Android开发
Android Mediatek NVRAM 加载 MAC 地址并禁用 MAC 地址更新
Android Mediatek NVRAM 加载 MAC 地址并禁用 MAC 地址更新
96 0
|
存储 缓存 编解码
Android Glide 的简单使用(一)(下)
Generated API 使用Generated API(高级用法) 定制请求 GlideExtension GlideOption GlideType submit同步获取图片资源 Application Options(选项) Memory cache(内存缓存) Disk Cache(磁盘缓存) Bitmap pool(位图池) 配置缓存 磁盘缓存策略(Disk Cache Strategy) 仅从缓存加载图片 跳过缓存 清理磁盘缓存 相关资源 Glide 缓存机制及源码(二) Glide git传送门 Glide中文文档 glide-transformations传送门
315 0
Android Glide 的简单使用(一)(下)