美文网首页android
关于安卓glide加载显示进度

关于安卓glide加载显示进度

作者: motosheep | 来源:发表于2022-06-10 08:46 被阅读0次

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

    相关文章

      网友评论

        本文标题:关于安卓glide加载显示进度

        本文链接:https://www.haomeiwen.com/subject/pdivmrtx.html