上一章链接:简单图片加载框架的打造(一)-框架设计
与Volley的代码一样,RequestQueue就是参考Volley设计的.
RequestQueue代码设计
RequestQueue
作为分发的源头,其一定持有一个Queue,然后持有Dispatchers来处理队列里面的请求.
既然需要队列,我们这种生产者消费者模式对队列的要求是:
- 线程安全
- 能够阻塞
- 能够优先级控制
这样我们的数据结构只能是: PriorityBlockingQueue
我们还需要分发器,从PriorityBlockingQueue
中不断的take(), 然后进行处理, 因此我们需要一个分发器列表.这里参考Volley源码,使用一个数组来存储,毕竟数组够完成任务了.
private RequestDispacher[] mRequestDispachers;
我们还需要提供方法去让主程序start自己.stop自己.
因此有了UML里面的start方法,stop方法.在这两个方法里面我们就开启分发器,关闭分发器就行了.
分发器RequestDispacher设计
分发器从PriorityBlockingQueue
中取请求, 我大Java可没有那种什么全局变量的玩意儿,把PriorityBlockingQueue的引用传给RequestDispacher
就行了,然后里面开一个线程不断的跑,从队列里取东西,进行消费就行了.
那么我们的RequestDispacher就可以写成继承于Thread类, 正好也有start/stop方法可以供调用.
代码编写
在往RequesQueue添加请求的时候,我们可以直接给ImageView设置加载中的图片,虽然这个请求还未被处理,也就是还未被加载中
,但是宏观来说,进入了我们的ImageLoader就已经是加载中了.
public class RequestQueue {
BlockingQueue<BitmapRequest> mRequestQueue = new PriorityBlockingQueue<>();
private AtomicInteger mNo = new AtomicInteger(0);
private int mThreadCount;
private RequestDispacher[] mRequestDispachers;
public RequestQueue(int threadCount) {
mThreadCount = threadCount;
}
/**
* start各个分发器
*/
public void start() {
mRequestDispachers = new RequestDispacher[mThreadCount];
for (int i = 0; i < mRequestDispachers.length; i++) {
RequestDispacher dispacher = new RequestDispacher(mRequestQueue);
mRequestDispachers[i] = dispacher;
dispacher.start();
}
}
/**
* 停止所有请求,以interrupt异常的方式
* 分发器也会停止运行
*/
public void stop() {
for (int i = 0; i < mRequestDispachers.length; i++) {
if (mRequestDispachers[i] != null) {
mRequestDispachers[i].quit();
}
}
}
/**
* 取消所有请求,但不停止分发器的运行
*/
public void cancel() {
for (BitmapRequest request : mRequestQueue) {
request.setCancel(true);
}
}
/**
* 根据tag取消请求
* @param tag
*/
public void cancel(Object tag) {
if (tag == null) {
return;
}
for (BitmapRequest request : mRequestQueue) {
if (tag.equals(request.getRequestTag())) {
request.setCancel(true);
}
}
}
public void addRequest(BitmapRequest request) {
if (!mRequestQueue.contains(request)) {
/** 设置唯一标识 */
request.setSerialNo(mNo.incrementAndGet());
mRequestQueue.add(request);
L.w("请求添加成功, 编号为:" + request.getSerialNo());
} else {
L.w("请求已经存在, 编号为:" + request.getSerialNo());
}
if (request.getDisplayConfig() != null
&& request.getDisplayConfig().loadingImage != -1) {
ImageView imageView = request.getImageView();
if (imageView != null && imageView.getTag().equals(request.getImageURL())) {
imageView.setImageResource(request.getDisplayConfig().loadingImage);
}
}
}
}
分发器的代码
/**
* 请求转发线程
* 依赖于BitmapRequest
* 依赖于Loader
* Created by xiamin on 7/8/17.
*/
public class RequestDispacher extends Thread {
private BlockingQueue<BitmapRequest> mBitmapRequests;
/** Used for telling us to die. */
private volatile boolean mQuit = false;
public RequestDispacher(BlockingQueue<BitmapRequest> requests) {
mBitmapRequests = requests;
}
/**
* Forces this dispatcher to quit immediately. If any requests are still in
* the queue, they are not guaranteed to be processed.
*/
public void quit() {
mQuit = true;
interrupt();
}
@Override
public void run() {
/**不断获取请求,处理请求*/
while (!isInterrupted()) {
try {
BitmapRequest bitmapRequest = mBitmapRequests.take();
if (bitmapRequest.isCancel()) {
continue;
}
L.d("开始处理" + bitmapRequest.getSerialNo() + "号请求,线程号:" + Thread.currentThread()
.getId());
/**
* 处理请求对象
*/
String type = parseURL(bitmapRequest.getImageURL());
ILoader l = LoaderManager.getInstance().getLoaderByType(type);
l.loadImage(bitmapRequest);
} catch (InterruptedException e) {
// We may have been interrupted because it was time to quit.
e.printStackTrace();
if (mQuit) {
return;
}
continue;
}
}
}
/**
* 解析图片来源
* @param imageURL
* @return
*/
private String parseURL(String imageURL) {
if (imageURL.contains("://")) {
return imageURL.split("://")[0];
}
L.e("不支持的URL:" + imageURL);
return " ";
}
}
下一章
下一章将讲解加载器缓存器的设计:简单图片加载框架的打造(三)-加载器缓存器设计
工程路径,里面还有我准备写的数据库lib,还有httplib,只看ImageLoaderlib即可. https://github.com/Jerey-Jobs/Sherlock
本文作者:Anderson/Jerey_Jobs
博客地址 : http://jerey.cn/
简书地址 : Anderson大码渣
github地址 : https://github.com/Jerey-Jobs