zoukankan      html  css  js  c++  java
  • 解析AndroidProject 加载圆角图片 GlideApp加载网络图片

    • 演示效果

      

    • 核心代码

      普通图片

     GlideApp.with(this)
                        .load("https://www.baidu.com/img/bd_logo.png")
                        .into(mImageView); 

      圆形图片

     GlideApp.with(this)
                        .load("https://www.baidu.com/img/bd_logo.png")
                        .circleCrop()
                        .into(mImageView);

      圆角图片

     GlideApp.with(this)
                        .load("https://www.baidu.com/img/bd_logo.png")
                        .transform(new RoundedCorners((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                                20, getResources().getDisplayMetrics())))
                        .into(mImageView);
    • 引用依赖

       build.gradle

       // 图片加载框架:https://github.com/bumptech/glide
        // 官方使用文档:https://muyangmin.github.io/glide-docs-cn/
        implementation 'com.github.bumptech.glide:glide:4.12.0'
        annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'

      ⭐由于以上加载的为网络图片,引入网络请求框架以及网络权限

        // 网络请求框架:https://github.com/getActivity/EasyHttp
        implementation 'com.hjq:http:9.0'
        // OkHttp 框架:https://github.com/square/okhttp
        // noinspection GradleDependency
        implementation 'com.squareup.okhttp3:okhttp:3.12.12'
    • 添加权限

      AndroidManifest.xml

     <uses-permission android:name="android.permission.INTERNET"></uses-permission>

    ⭐此时加载了Glide 依赖,但仍然无法使用GlideApp

    参考以下博文:GlideApp的由来

    Glide4.0源码全解析(一),GlideAPP和.with()方法背后的故事

    Glide4.0源码全解析(二),load()背后的故事

    Glide4.0源码全解析(三),into()方法背后的故事

    主要解决方法:创建一个类 extends AppGlideModule 添加 @GlideModule 注解

    • 添加AndroidProject的有关构建GlideApp代码

      

     GlideConfig.class

    package com.hjq.demo.http.glide;
    
    import android.content.Context;
    
    import androidx.annotation.NonNull;
    
    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.load.engine.bitmap_recycle.LruBitmapPool;
    import com.bumptech.glide.load.engine.cache.DiskLruCacheWrapper;
    import com.bumptech.glide.load.engine.cache.LruResourceCache;
    import com.bumptech.glide.load.engine.cache.MemorySizeCalculator;
    import com.bumptech.glide.load.model.GlideUrl;
    import com.bumptech.glide.module.AppGlideModule;
    import com.bumptech.glide.request.RequestOptions;
    import com.hjq.demo.R;
    import com.hjq.http.EasyConfig;
    
    import java.io.File;
    import java.io.InputStream;
    
    /**
     *    author : Android 轮子哥
     *    github : https://github.com/getActivity/AndroidProject
     *    time   : 2019/12/15
     *    desc   : Glide 全局配置
     */
    @GlideModule
    public final class GlideConfig extends AppGlideModule {
    
        /** 本地图片缓存文件最大值 */
        private static final int IMAGE_DISK_CACHE_MAX_SIZE = 500 * 1024 * 1024;
    
        @SuppressWarnings("ResultOfMethodCallIgnored")
        @Override
        public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
            // 读写外部缓存目录不需要申请存储权限
            File diskCacheFile = new File(context.getCacheDir(), "glide");
            // 如果这个路径是一个文件
            if (diskCacheFile.exists() && diskCacheFile.isFile()) {
                // 执行删除操作
                diskCacheFile.delete();
            }
            // 如果这个路径不存在
            if (!diskCacheFile.exists()) {
                // 创建多级目录
                diskCacheFile.mkdirs();
            }
            builder.setDiskCache(() -> DiskLruCacheWrapper.create(diskCacheFile, IMAGE_DISK_CACHE_MAX_SIZE));
    
            MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context).build();
            int defaultMemoryCacheSize = calculator.getMemoryCacheSize();
            int defaultBitmapPoolSize = calculator.getBitmapPoolSize();
    
            int customMemoryCacheSize = (int) (1.2 * defaultMemoryCacheSize);
            int customBitmapPoolSize = (int) (1.2 * defaultBitmapPoolSize);
    
            builder.setMemoryCache(new LruResourceCache(customMemoryCacheSize));
            builder.setBitmapPool(new LruBitmapPool(customBitmapPoolSize));
    
            builder.setDefaultRequestOptions(new RequestOptions()
                    // 设置默认加载中占位图
                    .placeholder(R.drawable.image_loading_bg)
                    // 设置默认加载出错占位图
                    .error(R.drawable.image_error_bg));
        }
    
        @Override
        public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
            // Glide 默认使用的是 HttpURLConnection 来做网络请求,这里切换成更高效的 OkHttp
            registry.replace(GlideUrl.class, InputStream.class, new OkHttpLoader.Factory(EasyConfig.getInstance().getClient()));
        }
    
        @Override
        public boolean isManifestParsingEnabled() {
            return false;
        }
    }

    OkHttpFetcher.class
    package com.vertex.myapplication.http.glide;
    
    import androidx.annotation.NonNull;
    
    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 com.bumptech.glide.load.model.GlideUrl;
    import com.bumptech.glide.util.ContentLengthInputStream;
    import com.bumptech.glide.util.Preconditions;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Map;
    
    import okhttp3.Call;
    import okhttp3.Callback;
    import okhttp3.Request;
    import okhttp3.Response;
    import okhttp3.ResponseBody;
    
    /**
     *    author : Android 轮子哥
     *    github : https://github.com/getActivity/AndroidProject
     *    time   : 2019/12/15
     *    desc   : OkHttp 加载器
     */
    public final class OkHttpFetcher implements DataFetcher<InputStream>, Callback {
    
        private final Call.Factory mCallFactory;
        private final GlideUrl mGlideUrl;
        private InputStream mInputStream;
        private ResponseBody mResponseBody;
        private DataCallback<? super InputStream> mDataCallback;
        private volatile Call mCall;
    
        OkHttpFetcher(Call.Factory factory, GlideUrl url) {
            mCallFactory = factory;
            mGlideUrl = url;
        }
    
        @Override
        public void loadData(@NonNull Priority priority, @NonNull final DataCallback<? super InputStream> callback) {
            Request.Builder requestBuilder = new Request.Builder().url(mGlideUrl.toStringUrl());
            for (Map.Entry<String, String> headerEntry : mGlideUrl.getHeaders().entrySet()) {
                String key = headerEntry.getKey();
                requestBuilder.addHeader(key, headerEntry.getValue());
            }
            Request request = requestBuilder.build();
            mDataCallback = callback;
    
            mCall = mCallFactory.newCall(request);
            mCall.enqueue(this);
        }
    
        @Override
        public void onFailure(@NonNull Call call, @NonNull IOException e) {
            mDataCallback.onLoadFailed(e);
        }
    
        @Override
        public void onResponse(@NonNull Call call, @NonNull Response response) {
            mResponseBody = response.body();
            if (response.isSuccessful()) {
                long contentLength = Preconditions.checkNotNull(mResponseBody).contentLength();
                mInputStream = ContentLengthInputStream.obtain(mResponseBody.byteStream(), contentLength);
                mDataCallback.onDataReady(mInputStream);
            } else {
                mDataCallback.onLoadFailed(new HttpException(response.message(), response.code()));
            }
        }
    
        @Override
        public void cleanup() {
            try {
                if (mInputStream != null) {
                    mInputStream.close();
                }
            } catch (IOException ignored) {}
    
            if (mResponseBody != null) {
                mResponseBody.close();
            }
            mDataCallback = null;
        }
    
        @Override
        public void cancel() {
            if (mCall != null) {
                mCall.cancel();
            }
        }
    
        @NonNull
        @Override
        public Class<InputStream> getDataClass() {
            return InputStream.class;
        }
    
        @NonNull
        @Override
        public DataSource getDataSource() {
            return DataSource.REMOTE;
        }
    }

     OkHttpLoader.class

    package com.hjq.demo.http.glide;
    
    import androidx.annotation.NonNull;
    
    import com.bumptech.glide.load.Options;
    import com.bumptech.glide.load.model.GlideUrl;
    import com.bumptech.glide.load.model.ModelLoader;
    import com.bumptech.glide.load.model.ModelLoaderFactory;
    import com.bumptech.glide.load.model.MultiModelLoaderFactory;
    
    import java.io.InputStream;
    
    import okhttp3.Call;
    
    /**
     *    author : Android 轮子哥
     *    github : https://github.com/getActivity/AndroidProject
     *    time   : 2019/12/15
     *    desc   : OkHttp 加载模型
     */
    public final class OkHttpLoader implements ModelLoader<GlideUrl, InputStream> {
    
        private final Call.Factory mFactory;
    
        private OkHttpLoader(@NonNull Call.Factory factory) {
            mFactory = factory;
        }
    
        @Override
        public boolean handles(@NonNull GlideUrl url) {
            return true;
        }
    
        @Override
        public LoadData<InputStream> buildLoadData(@NonNull GlideUrl model, int width, int height, @NonNull Options options) {
            return new LoadData<>(model, new OkHttpFetcher(mFactory, model));
        }
    
        public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
    
            private final Call.Factory mFactory;
    
            Factory(@NonNull Call.Factory factory) {
                mFactory = factory;
            }
    
            @NonNull
            @Override
            public ModelLoader<GlideUrl, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) {
                return new OkHttpLoader(mFactory);
            }
    
            @Override
            public void teardown() {}
        }
    }
    •  GlideConfig占位图

    Android vector 参考博文:Android Studio神器之Vector Asset

    R.drawable.image_loading_bg

    <?xml version="1.0" encoding="utf-8"?>
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="180dp"
        android:height="180dp"
        android:viewportWidth="180"
        android:viewportHeight="180">
    
        <path
            android:fillColor="@color/black"
            android:fillAlpha="0.18"
            android:strokeAlpha="0.18"
            android:pathData="M116.69,42.5 C118.34,42.3,120.68,41.43,121.74,43.27
    C122.94,46.03,123.19,49.07,123.84,51.98 C124.39,55.2,125.59,58.45,124.77,61.74
    C110.83,60.27,96.93,58.41,83.01,56.68 C79.82,56.36,76.64,55.92,73.55,55.04
    C74.11,53.54,74.86,51.92,76.67,51.72 C89.99,48.59,103.36,45.63,116.69,42.5 Z" />
        <path
            android:fillColor="@color/black"
            android:fillAlpha="0.18"
            android:strokeAlpha="0.18"
            android:pathData="M39.17,62.06 C39.85,59.59,42.92,59.71,44.91,59.02
    C45.75,64.24,44.56,69.47,43.63,74.6 C43.05,74.66,41.91,74.77,41.34,74.83
    C40.41,70.62,39.1,66.41,39.17,62.06 Z" />
        <path
            android:fillColor="@color/black"
            android:fillAlpha="0.18"
            android:strokeAlpha="0.18"
            android:pathData="M55.17,63.02 C56.68,62.27,58.44,62.9,60.04,62.93
    C85.05,66.1,110.07,69.09,135.08,72.19 C138.1,72.15,139.04,75.49,138.56,77.95
    C136.78,94.98,134.69,111.99,132.7,129 C132.23,132.41,132.31,135.96,131.14,139.24
    C129.69,141.09,127.08,140.18,125.09,140.15
    C102.51,137.22,79.9,134.5,57.32,131.53 C54.25,131.04,51,131.11,48.08,129.93
    C46.39,128.87,46.92,126.63,46.99,124.98 C49.21,106.65,51.23,88.31,53.18,69.95
    C53.69,67.69,53.14,64.57,55.17,63.02 M118.3,81.47
    C114.1,83.2,112.65,88.96,115.62,92.43 C118.38,96.38,125.14,95.34,126.76,90.86
    C128.97,85.83,123.8,79.05,118.3,81.47 M84.19,87.31
    C82.76,88.13,81.59,89.33,80.43,90.49 C73.1,98.12,65.54,105.54,58.11,113.07
    C56.74,114.2,56.52,116.68,58.35,117.48 C61.47,118.46,64.76,118.66,67.99,119.05
    C79.67,120.21,91.26,122.13,102.94,123.32 C108.96,123.91,114.94,125.48,121,125.15
    C122.17,125.26,123.01,123.61,122.26,122.73
    C118.02,115.66,113.63,108.67,109.28,101.66
    C108.33,100.31,107.51,98.68,105.95,97.94 C102.43,97.99,100.63,103.03,97.03,101.9
    C93.15,97.93,91.6,92.26,87.88,88.14 C86.97,87.13,85.45,86.64,84.19,87.31 Z" />
    </vector>

    R.drawable.image_error_bg

    <?xml version="1.0" encoding="utf-8"?>
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="180dp"
        android:height="180dp"
        android:viewportWidth="180"
        android:viewportHeight="180">
    
        <path
            android:fillAlpha="0.18"
            android:fillColor="@color/black"
            android:pathData="M43.81,52.8 C45.6,50.77,48.52,51.06,50.96,50.96
    C66.31,51.08,81.66,50.92,97.01,51.04 C95.9,55.94,94.85,60.85,93.65,65.73
    C92.59,70.05,88.83,72.85,86.23,76.23 C82.75,80.75,77.93,84.49,76.21,90.12
    C71.8,103.07,67.12,115.92,62.69,128.86 C57.47,128.98,52.24,129.3,47.04,128.82
    C43.75,128.52,41.71,125.09,42.01,121.98 C41.95,101.33,42.07,80.68,41.96,60.03
    C42.06,57.56,41.75,54.61,43.81,52.8 M62.28,66.36
    C57.05,67.76,55.21,75.2,59.27,78.81 C63.12,83.04,70.98,80.6,71.83,74.97
    C73.14,69.67,67.41,64.51,62.28,66.36 Z"
            android:strokeAlpha="0.18" />
    
        <path
            android:fillAlpha="0.18"
            android:fillColor="@color/black"
            android:pathData="M113.09,51.02 C119.42,51.05,125.76,50.82,132.09,51.08
    C135.68,50.97,138.36,54.51,137.99,57.94 C138.05,78.63,137.93,99.32,138.04,120.01
    C137.94,122.48,138.23,125.42,136.18,127.23
    C134.37,129.24,131.45,128.94,129.01,129.04
    C107.67,128.93,86.33,129.07,64.99,128.97 C72.1,115.15,79.43,101.45,86.52,87.62
    C89.39,81.43,95.26,77.57,99.86,72.79 C104.5,68.7,105.29,62.22,108.21,57.06
    C109.37,54.7,111.32,52.91,113.09,51.02 M112.33,85.3
    C107.87,91.59,105.61,99.19,101.45,105.68
    C101.1,105.77,100.4,105.96,100.05,106.05 C96.75,102.67,96.3,97.32,92.83,94.08
    C90.19,92.61,88.59,95.75,87.63,97.68 C85.26,102.87,82.23,107.77,80.21,113.11
    C78.99,115.54,81.76,117.35,83.95,116.96 C97.3,117.1,110.65,116.92,124,117.04
    C125.72,116.89,127.67,117.19,129.19,116.21
    C130.93,114.51,129.46,112.14,128.7,110.34
    C124.84,102.81,121.14,95.19,117.31,87.64 C116.51,85.71,114.42,83.63,112.33,85.3
    Z"
            android:strokeAlpha="0.18" />
    </vector>

  • 相关阅读:
    微信小程序错误码参考大全
    关于vagrant一个虚拟机搭建多个项目配置(总结)
    Vagrant安装完lnmp后,配置linux和windows共享文件并配置虚拟主机访问项目
    vagrant的centos镜像,怎么用root用户登录?
    Vagrant系列(二)----Vagrant的配置文件Vagrantfile详解
    过滤数组中的空数组array_filter()
    getMessage(),getFile,getLine获取异常用法
    测试工程师的福利!各远程移动测试平台对比分析
    学习这篇总结后,你也能做出天天快报一样的推荐系统
    别被官方文档迷惑了!这篇文章帮你详解yarn公平调度
  • 原文地址:https://www.cnblogs.com/xqz0618/p/14901106.html
Copyright © 2011-2022 走看看