一鍵打造自己的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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章