Picasso--设计思路浅析

2017-09-26  本文已影响0人  Qi0907

Picasso结构图


Paste_Image.png

Picasso流程图


Paste_Image.png

Picasso中的核心类包括Picasso、Dispatcher、BitmapHunter、RequestHandler、Request、Action、Cache等。
Picasso类是一个负责图片下载、变换、缓存的管理器,当它收到一个图片下载请求的时候,它会创建Request并提交给Dispatcher。load负责加载网络图片,into负责把图片显示到组件中。

public void into(ImageView target, Callback callback) {
        …
        ImageViewAction action1 = new ImageViewAction(this.picasso, target, request1, this.memoryPolicy, this.networkPolicy, this.errorResId, this.errorDrawable, requestKey1, this.tag, callback, this.noFade);
        this.picasso.enqueueAndSubmit(action1);
    }
}

可以看到into最后通过picasso.enqueueAndSubmit提交到队列,每一个请求对应一个action,每个图片都会into到组件中,因此会有很多action交给Picasso执行,这时就需要Dispatcher进行分发和执行。

void enqueueAndSubmit(Action action) {
    Object target = action.getTarget();
    if(target != null && this.targetToAction.get(target) != action) {
        this.cancelExistingRequest(target);
        this.targetToAction.put(target, action);
    }
    this.submit(action);
}

void submit(Action action) {
    this.dispatcher.dispatchSubmit(action);
}

Dispatcher是在Picasso被创建前实例化的,并作为picasso的一个成员变量

public Picasso build() {
    Context context = this.context;
    …
    Dispatcher dispatcher = new Dispatcher(context, this.service, Picasso.HANDLER, this.downloader, this.cache, stats);
    …
}

在Dispatcher的构造函数中开启了一个消息循环线程DispatcherThread(DispatcherThread是一个HandlerThread,也就是一个带有Looper的线程),之后用DispatcherThread的Looper实例化了一个Handler,用来处理消息循环线程的所有消息。

Dispatcher(Context context, ExecutorService service, Handler mainThreadHandler, Downloader downloader, Cache cache, Stats stats) {
    this.dispatcherThread.start();
    …
    this.handler = new Dispatcher.DispatcherHandler(this.dispatcherThread.getLooper(), this);
    …
}
final Dispatcher.DispatcherThread dispatcherThread = new Dispatcher.DispatcherThread();
static class DispatcherThread extends HandlerThread {
    DispatcherThread() {
        super("Picasso-Dispatcher", 10);
    }
}

这样Dispatcher的消息循环机制就建立起来了。
根据上面介绍into->picasso.enqueueAndSubmit->submit-> dispatcher.dispatchSubmit

void dispatchSubmit(Action action) {
    this.handler.sendMessage(this.handler.obtainMessage(REQUEST_SUBMIT
, action));
}

可以看到是通过Handler向HandlerThread发消息进行分发的。根据Hander机制,最终消息在Handler的 handlerMessage()回调中被处理, action的其他操作,也通过这种方式进行分发和处理。

public void handleMessage(final Message msg) {
    Object info;
    BitmapHunter info2;
    Action info3;
    switch(msg.what) {
        case REQUEST_SUBMIT:
            info3 = (Action)msg.obj;
            this.dispatcher.performSubmit(info3);
            break;
        …
    }
}

action的执行通过dispatcher.performSubmit

void performSubmit(Action action) {
    this.performSubmit(action, true);
}

void performSubmit(Action action, boolean dismissFailed) {
    //action是否被暂停
    if(this.pausedTags.contains(action.getTag())) {
        …
    } else {
        //从hunter map里查找当前action所关联的hunter,有就直接使用
        BitmapHunter hunter = (BitmapHunter)this.hunterMap.get(action.getKey());
        if(hunter != null) {
            …
        } else if(this.service.isShutdown()) {
            …
    } else {
            //创建BitmapHunter
            hunter = BitmapHunter.forRequest(action.getPicasso(), this, this.cache, this.stats, action);
            //提交到线程池中执行
            hunter.future = this.service.submit(hunter);
            //把此hunter加入到hunter map中
            this.hunterMap.put(action.getKey(), hunter);
            …
        }
    }
}

可以看到这里BitmapHunter出场了,忽略掉异常情况,可以看到是由forRequest()创建该action的BitMapHunter,之后提交到线程池中并加入到hunter map中。
再来看BitMapHunter

class BitmapHunter implements Runnable

可以看到BitmapHunter其实是一个Runnable,在线程池上执行的是其run()方法

Bitmap result;
public void run() {
     …
     this.result = this.hunt();//获得bitmap
     if(this.result == null) {//通过dispatcher分发处理
        this.dispatcher.dispatchFailed(this);
     } else {
        this.dispatcher.dispatchComplete(this);
     }
     …
}

忽略掉异常情况,bitmap是通过hunt这个方法获得的, 然后将结果通过Dispatcher进行分发处理
进入到hunt中看如何获得bitmap

Bitmap hunt() throws IOException {
    Bitmap bitmap = null;
    …
    Result result = this.requestHandler.load(this.data, this.networkPolicy);
    if(result != null) {
        …
        bitmap = result.getBitmap();
        …
    }
    …
    }

    return bitmap;
}

忽略掉异常情况, Bitmap最终是由BitmapHunter的requestHandler.load()方法获取的, Picasso默认提供了ResourceRequestHandler、ContactsPhotoRequestHandler、MediaStoreRequestHandler、ContentStreamRequestHandler、 AssetRequestHandler、FileRequestHandler、NetworkRequestHandler等7中RequestHandler,用来从不同的来源获取Bitmap。

上一篇下一篇

猜你喜欢

热点阅读