Parsing Android project loading fillet image and slideapp loading network image

Time:2021-10-25

 

  • Demonstration effect

  

 

  • Core code

Ordinary picture

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

Circular picture

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

Fillet picture

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);

 

  • Reference dependency

   build.gradle

//Picture loading frame: https://github.com/bumptech/glide
    //Official documents: 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'

⭐ Since the above loaded pictures are network pictures, the network request framework and network permissions are introduced

//Network request framework: https://github.com/getActivity/EasyHttp
    implementation 'com.hjq:http:9.0'
    //Okhttp framework: https://github.com/square/okhttp
    // noinspection GradleDependency
    implementation 'com.squareup.okhttp3:okhttp:3.12.12'

 

  • add permission

  AndroidManifest.xml

 

⭐ Glide dependencies are loaded at this time, but glideapp is still unavailable

Refer to the following blog post: the origin of glideapp

Glide4.0 source code full analysis (I), the story behind glideapp and. With () methods

Glide4.0 source code full analysis (II), the story behind load ()

Glide4.0 source code full analysis (III), the story behind the into () method

Main solution: create a class extends AppGlideModuleadd to  @GlideModule annotation

 

  • Add Android project’s code for building 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 wheel
 *    github : https://github.com/getActivity/AndroidProject
 *    time   : 2019/12/15
 *Desc: glide global configuration
 */
@GlideModule
public final class GlideConfig extends AppGlideModule {

    /**Local picture cache file maximum*/
    private static final int IMAGE_DISK_CACHE_MAX_SIZE = 500 * 1024 * 1024;

    @SuppressWarnings("ResultOfMethodCallIgnored")
    @Override
    public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
        //You do not need to apply for storage permission to read and write the external cache directory
        File diskCacheFile = new File(context.getCacheDir(), "glide");
        //If this path is a file
        if (diskCacheFile.exists() && diskCacheFile.isFile()) {
            //Perform delete operation
            diskCacheFile.delete();
        }
        //If this path does not exist
        if (!diskCacheFile.exists()) {
            //Create multi-level directory
            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()
                //Set the default load bitmap
                .placeholder(R.drawable.image_loading_bg)
                //Set default load error bitmap
                .error(R.drawable.image_error_bg));
    }

    @Override
    public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
        //Glide uses httpurlconnection by default to make network requests. Here, it switches to okhttp, which is more efficient
        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 wheel
 *    github : https://github.com/getActivity/AndroidProject
 *    time   : 2019/12/15
 *Desc: okhttp loader
 */
public final class OkHttpFetcher implements DataFetcher, 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 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 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 wheel
 *    github : https://github.com/getActivity/AndroidProject
 *    time   : 2019/12/15
 *Desc: okhttp loading model
 */
public final class OkHttpLoader implements ModelLoader {

    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 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 {

        private final Call.Factory mFactory;

        Factory(@NonNull Call.Factory factory) {
            mFactory = factory;
        }

        @NonNull
        @Override
        public ModelLoader build(@NonNull MultiModelLoaderFactory multiFactory) {
            return new OkHttpLoader(mFactory);
        }

        @Override
        public void teardown() {}
    }
}

 

  • Glideconfig bitmap

Android vector reference blog:Vector asset of Android studio artifact

R.drawable.image_loading_bg

 

R.drawable.image_error_bg

 

Recommended Today

Swift advanced (XV) extension

The extension in swift is somewhat similar to the category in OC Extension can beenumeration、structural morphology、class、agreementAdd new features□ you can add methods, calculation attributes, subscripts, (convenient) initializers, nested types, protocols, etc What extensions can’t do:□ original functions cannot be overwritten□ you cannot add storage attributes or add attribute observers to existing attributes□ cannot add parent […]