知识点1 把请求Builder加入到队列中,开启一个任务处理队列,用Handler处理结果
package com.example.glidelibrary.task;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import com.example.glidelibrary.RequestBuilder;
import com.example.glidelibrary.exception.GlideException;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.LinkedBlockingQueue;
/**
* 加载任务
*/
public class DispatcherTask extends Thread {
private Handler handler;
private LinkedBlockingQueue<RequestBuilder> blockingQueue;
public DispatcherTask(LinkedBlockingQueue<RequestBuilder> blockingQueue) {
this.blockingQueue = blockingQueue;
handler = new Handler(Looper.getMainLooper());
}
@Override
public void run() {
super.run();
//只要线程没有中断,一直轮训
while (!isInterrupted()) {
try {
//从队列中获取请求对象
RequestBuilder requestBuilder = blockingQueue.take();
//设置占位符
placeHolder(requestBuilder);
//从网路加载图片
Bitmap bitmap = loadFromNet(requestBuilder);
//显示到控件
showBitmap(requestBuilder, bitmap);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void showBitmap(final RequestBuilder requestBuilder, final Bitmap bitmap) {
if (bitmap != null
&& requestBuilder.getImageView().get() != null
&& requestBuilder.getImageView().get().getTag() == requestBuilder.getMd5FileName()) {
handler.post(new Runnable() {
@Override
public void run() {
requestBuilder.getImageView().get().setImageBitmap(bitmap);
if (requestBuilder.getRequestListener() != null) {
requestBuilder.getRequestListener().onResourceReady(bitmap);
}
}
});
}
}
private Bitmap loadFromNet(RequestBuilder requestBuilder) {
InputStream is = null;
Bitmap bitmap = null;
try {
URL url = new URL(requestBuilder.getUrl());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
is = getInpuStream(connection);
bitmap = BitmapFactory.decodeStream(is);
is.close();
} catch (Exception e) {
e.printStackTrace();
requestBuilder.getRequestListener().onLoadFailed(e);
} finally {
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return bitmap;
}
public InputStream getInpuStream(HttpURLConnection urlConnection) throws IOException {
int code = urlConnection.getResponseCode();
if (code == 302) {
String location = urlConnection.getHeaderField("Location");
return getInpuStream((HttpURLConnection) new URL(location).openConnection());
} else if (urlConnection.getResponseCode() == 200) {
return urlConnection.getInputStream();
}
return null;
}
private void placeHolder(final RequestBuilder requestBuilder) {
if (requestBuilder.getPlaceHolderId() > 0 && requestBuilder.getImageView() != null) {
handler.post(new Runnable() {
@Override
public void run() {
requestBuilder.getImageView().get().setImageResource(requestBuilder.getPlaceHolderId());
}
});
}
}
}
三级缓存
- 首次从网络获取,并缓存下来
- 从对象获取
- 对象中没有从内存中获取
- 内存中没有从磁盘上获取
- 磁盘没有重新从网路获取
相关依赖库
compile 'com.jakewharton:disklrucache:2.0.2'
相关代码
package com.gameassist.plugin.mod.utils;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.util.Log;
import android.util.LruCache;
import com.jakewharton.disklrucache.DiskLruCache;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import static android.os.Environment.isExternalStorageRemovable;
/**
* Created by ljp on 2018/8/16.
*/
public class LruCacheUtils {
private static final String TAG = "ggplugin";
private static final int IO_BUFFER_SIZE = 4096;
@SuppressLint("StaticFieldLeak")
private volatile static LruCacheUtils lruCacheUtil;
private Context context;
private static final int MAX_SIZE = 10 * 1024 * 1024;//10MB
private DiskLruCache diskLruCache;
// 获取可用内存的最大值,使用内存超出这个值将抛出 OutOfMemory 异常。LruCache 通过构造函数传入缓存值,以 KB 为单位。
private final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // 把最大可用内存的 1/8 作为缓存空间
private final int cacheSize = maxMemory / 8;
public static synchronized LruCacheUtils getInstance() {
if (null == lruCacheUtil) {
synchronized (ClientUtils.class) {
if (lruCacheUtil == null) {
lruCacheUtil = new LruCacheUtils();
}
}
}
return lruCacheUtil;
}
private LruCache<String, Bitmap> mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getByteCount() / 1024;
}
};
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
mMemoryCache.put(key, bitmap);
}
}
public Bitmap getBitmapFromMemCache(String key) {
return mMemoryCache.get(key == null ? "" : key);
}
public static File getDiskCacheDir(Context context, String uniqueName) {
final String cachePath = Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !isExternalStorageRemovable()
? context.getExternalCacheDir().getPath() : context.getCacheDir().getPath();
return new File(cachePath + File.separator + uniqueName);
}
public static File getDiskFilesDir(Context context, String uniqueName) {
final String cachePath = Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !isExternalStorageRemovable()
? context.getExternalFilesDir(null).getPath() : context.getFilesDir().getPath();
return new File(cachePath + File.separator + uniqueName);
}
public void initDiskLruCache(Context context) {
this.context = context;
if (diskLruCache == null || diskLruCache.isClosed()) {
try {
File cacheDir = getDiskFilesDir(context, "CacheDir");
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
//初始化DiskLruCache
diskLruCache = DiskLruCache.open(cacheDir, 1, 1, MAX_SIZE);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* A hashing method that changes a string (like a URL) into a hash suitable for using as a
* disk filename.
*/
public static String hashKeyForDisk(String key) {
String cacheKey;
try {
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(key.getBytes());
cacheKey = bytesToHexString(mDigest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(key.hashCode());
}
return cacheKey;
}
private static String bytesToHexString(byte[] bytes) {
// http://stackoverflow.com/questions/332079
StringBuilder sb = new StringBuilder();
for (byte aByte : bytes) {
String hex = Integer.toHexString(0xFF & aByte);
if (hex.length() == 1) {
sb.append('0');
}
sb.append(hex);
}
return sb.toString();
}
boolean lruHttpBitmap(String url) {
try {
String key = hashKeyForDisk(url);
//得到DiskLruCache.Editor
DiskLruCache.Editor editor = diskLruCache.edit(key);
if (editor != null) {
OutputStream outputStream = editor.newOutputStream(0);
if (downloadUrlToStream(url, outputStream)) {
// if (HttpUtils.getInstance(context).networkHttpRequest(url, outputStream)) {
// publishProgress("");
//写入缓存
editor.commit();
} else {
//写入失败
editor.abort();
}
}
diskLruCache.flush();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
public void putDiskValue(String url, InputStream inputStream) {
try {
String key = hashKeyForDisk(url);
//得到DiskLruCache.Editor
DiskLruCache.Editor editor = diskLruCache.edit(key);
if (editor != null) {
OutputStream outputStream = editor.newOutputStream(0);
byte[] buffer = new byte[1024];//out写的时候,每次写1024个字节,如果in有2048个字节数,则读2048/1024=2次
int len;
while ((len = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, len);
}
editor.commit();
outputStream.close();
}
inputStream.close();
diskLruCache.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public Bitmap getDiskValue(String url) {
if (diskLruCache != null) {
try {
DiskLruCache.Snapshot snapshot = diskLruCache.get(hashKeyForDisk(url));
if (snapshot != null) {
return BitmapFactory.decodeStream(snapshot.getInputStream(0));
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* Download a bitmap from a URL and write the content to an output stream.
*
* @param urlString The URL to fetch
* @return true if successful, false otherwise
*/
private boolean downloadUrlToStream(String urlString, OutputStream outputStream) {
HttpURLConnection urlConnection = null;
BufferedOutputStream out = null;
BufferedInputStream in = null;
try {
final URL url = new URL(urlString);
urlConnection = (HttpURLConnection) url.openConnection();
if (urlConnection != null) {
// InputStream inputStream = urlConnection.getInputStream();
InputStream inputStream = getInpuStream(urlConnection);
if (inputStream != null) {
in = new BufferedInputStream(inputStream);
out = new BufferedOutputStream(outputStream);
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
return true;
}
}
} catch (Exception e) {
Log.e(TAG, "Error in downloadBitmap - " + e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (final IOException ignored) {
}
}
return false;
}
public InputStream getInpuStream(HttpURLConnection urlConnection) {
try {
int code = urlConnection.getResponseCode();
LogUtils.e("code" + code);
if (code == 302) {
String location = urlConnection.getHeaderField("Location");
return getInpuStream((HttpURLConnection) new URL(location).openConnection());
} else if (urlConnection.getResponseCode() == 200) {
return urlConnection.getInputStream();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}