一键打造自己的Gilde图片加载控件

自定义Gilde的使用与解释

例子

  1. Gilde控件是一个图片加载的一个工具。优点性能高,流式api。使用例子是如下
LDGlide.with(this).load("http://url").
                loading(R.mipmap.ic_launcher).listener(new RequestListener() {
            @Override
            public boolean onSuccess(Bitmap bitmap) {
                return false;
            }

            @Override
            public boolean onFailure() {
                return false;
            }
        }).into(imageView);

使用说明

  1. 其中url是你要请求的网络地址,loading是图片加载的占位图可以放一张动态图作为加载时显示的。listener是监听类。当加载成功的时候返回一个Bitmap,进行后续的逻辑设计。into是将加载的图片放到图片控件里面。

gilde控件高效性主要来源于线程的管理下面介绍一下生活中的例子来设计gilde。

顾客到联通营业厅的例子来设计glide控件。

联通营业厅管理着柜台和顾客,顾客相当于请求,柜台管理员相当于图片加载调度员。

顾客是一个队列,图片加载调度员是几个线程

先定义一个图片请求对象封装类如下

package com.tydfd.netgilde.netglide;

/**
 * @Classname BitmapRequest
 * @Description 图片请求对象封装类
 * @Date 2019/7/16 8:42
 * @Created by liudo
 * @Author by liudo
 */

import android.content.Context;
import android.widget.ImageView;

import com.tydfd.netgilde.MD5Utils;

import java.lang.ref.SoftReference;
public class BitmapRequest {
    /**
     * 请求路径
     */
    private String url;

    /**
     * 上下文
     */
    private Context mContext;

    /**
     * 需要加载图片的控件
     */
    private SoftReference<ImageView> mImageView;

    /**
     * 占位图片
     */
    private int resID;

    /**
     * 回调对象
     */
    private RequestListener mRequestListener;

    /**
     * 图片的标识
     */
    private String urlMd5;

    public BitmapRequest(Context context){
        this.mContext = context;
    }

    public String getUrl() {
        return url;
    }

    public Context getContext() {
        return mContext;
    }

    public ImageView getImageView() {
        return mImageView.get();
    }


    public int getResID() {
        return resID;
    }


    public RequestListener getRequestListener() {
        return mRequestListener;
    }


    public String getUrlMd5() {
        return urlMd5;
    }

    /**
     * 链式调度
     * 加载url
     * @param url
     * @return
     */
    public BitmapRequest load(String url){
        this.url = url;
        this.urlMd5 = MD5Utils.toMD5(url);
        return this;
    }

    /**
     * 设置占位图片
     * @param resID
     * @return
     */
    public BitmapRequest loading(int resID){
        this.resID = resID;
        return this;
    }

    /**
     * 设置监听
     * @param listener
     * @return
     */
    public BitmapRequest listener(RequestListener listener){
        this.mRequestListener = listener;
        return this;
    }

    public void into(ImageView imageView){
        imageView.setTag(this.urlMd5);
        this.mImageView = new SoftReference<>(imageView);
        RequestManager.getInstance().addBitmapRequest(this);
    }


}
  1. SoftReference软引用的使用

    如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。

    防止ImagView被内存回收导致程序崩溃

  2. MD5URL图片标识                                                                                                                                                                   图片的唯一性,用来防止图片混乱。
  3. 链式调度加载

通过链式加载让逻辑更加清晰,有助于管理参数。

package com.tydfd.netgilde.netglide;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.widget.ImageView;

import com.tydfd.netgilde.MyApplication;
import com.tydfd.netgilde.cache.DoubleLruCache;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @Classname BitmapDispatcher
 * @Description TODO
 * @Date 2019/7/16 9:29
 * @Created by liudo
 * @Author by liudo
 */
public class BitmapDispatcher extends Thread {

    private Handler mHandler = new Handler(Looper.getMainLooper());
    /**
     * 创建一个堵塞队列
     */
    private LinkedBlockingQueue<BitmapRequest> requestQueue;
    public BitmapDispatcher(LinkedBlockingQueue<BitmapRequest> requestQueue){
        this.requestQueue = requestQueue;
    }

    @Override
    public void run() {
        super.run();
        /**
         * 当线程没有被打断的时候
         */
        while (!isInterrupted()){
            try {
                BitmapRequest br = requestQueue.take();
            /**
             * 设置占位图片
             */
            showLoadingImag(br);
            /**
             * 加载图片
             */
            Bitmap bitmap = findBitMap(br);
            /**
             * 把图片显示到ImageView
             */
            showImageView(br,bitmap);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    private void showImageView(final BitmapRequest br, final Bitmap bitmap) {
        if(bitmap!=null&&br.getImageView() != null &&
            br.getUrlMd5().equals(br.getImageView().getTag())){
            final ImageView imageView = br.getImageView();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    imageView.setImageBitmap(bitmap);
                    if(br.getRequestListener() != null){
                        RequestListener listener = br.getRequestListener();
                        listener.onSuccess(bitmap);
                    }
                }
            });
        }
    }

    private Bitmap findBitMap(BitmapRequest br) {
        Bitmap bitmap = downloadImage(br.getUrl()); 
        return bitmap;
    }

    private Bitmap downloadImage(String uri) {
        FileOutputStream fos = null;
        InputStream is = null;
        Bitmap bitmap = null;

        try {
            /**
             * 创建一个URL对象
             */
            URL url = new URL(uri);
            /**
             * 然后使用HttpURLConnection通过URL去开始读取数据
             */
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            is = conn.getInputStream();

            bitmap = BitmapFactory.decodeStream(is);
        }catch (Exception e){
            e.printStackTrace();
        }finally {

            try
            {
                if (is != null){
                    is.close();
                }
            } catch (IOException e)
            {
                e.printStackTrace();
            }

            try
            {
                if (fos != null){
                    fos.close();
                }
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        return bitmap;
    }

    private void showLoadingImag(BitmapRequest br) {
        if(br.getResID() > 0
        && br.getImageView() != null){
            final int resID = br.getResID();
            final ImageView imageView = br.getImageView();

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    imageView.setImageResource(resID);
                }
            });
        }

    }
}

如果当前线程没有被打断的时候继续相应请求的流程否则直接停止相应

银行管理类也即请求管理类

package com.tydfd.netgilde.netglide;

import java.util.concurrent.LinkedBlockingQueue;

/**
 * @Classname RequestManager
 * @Description TODO
 * @Date 2019/7/16 10:16
 * @Created by liudo
 * @Author by liudo
 */
public class RequestManager {

    private static RequestManager sRequestManager = new RequestManager();
    /**
     * 创建阻塞队列
     */
    private LinkedBlockingQueue<BitmapRequest> requestQueue = new LinkedBlockingQueue<>();

    private BitmapDispatcher[] mBitmapDispatchers;
    
    private RequestManager(){
        start();
    }

    /**
     * 开启所有线程的总开关
     */
    private void start() {
        stop();
        startAllDispatcher();
    }

    /**
     * 将图片请求对象添加到队列中去
     * @param bitmapRequest
     */
    public void addBitmapRequest(BitmapRequest bitmapRequest){
        if(bitmapRequest == null){
            return;
        }
        /**
         * 判断当前请求是否在队列中
         */
        if(!requestQueue.contains(bitmapRequest)){
            requestQueue.add(bitmapRequest);
        }
    }
    /**
     * 停止所有的线程
     */
    private void stop() {
        if(mBitmapDispatchers != null && mBitmapDispatchers.length > 0){
            for (BitmapDispatcher bitmapDispatcher : mBitmapDispatchers){
                if(!bitmapDispatcher.isInterrupted()){
                    bitmapDispatcher.interrupt();
                }
            }
        }
    }

    /**
     * 创建并开始所有的线程
     */
    private void startAllDispatcher() {
        /**
         * 获取手机支持的单个应用最大的线程数
         */
        int threadCount = Runtime.getRuntime().availableProcessors();

        mBitmapDispatchers = new BitmapDispatcher[threadCount];
        for (int i = 0; i < threadCount; i++){
            BitmapDispatcher bitmapDispatcher = new BitmapDispatcher(requestQueue);
            bitmapDispatcher.start();
            /**
             * 要将每个dispatcher放到数组中,方便统一管理
             */
            mBitmapDispatchers[i] = bitmapDispatcher;
        }

    }

    public static  RequestManager getInstance(){
        return sRequestManager;
    }
}

银行管理,管理顾客和图片加载调度员,也即请求管理管理请求类和请求响应类,为请求创建队列,管理请求相应执行顺序

整个思路很简单,首先请求类在队列排队,请求相应类在柜台等待执行请求,请求管理安排请求响应什么时候加载请求。通过队列的方式请求网络,使用 HttpURLConnection加载图片流。内容很简单。可以扩展三级缓存什么的。

Demo地址为https://download.csdn.net/download/qq_38366111/11376051

发布了22 篇原创文章 · 获赞 4 · 访问量 4334

猜你喜欢

转载自blog.csdn.net/qq_38366111/article/details/96307076