美文网首页
Picasso--设计思路浅析

Picasso--设计思路浅析

作者: Qi0907 | 来源:发表于2017-09-26 16:46 被阅读0次

    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。

    相关文章

      网友评论

          本文标题:Picasso--设计思路浅析

          本文链接:https://www.haomeiwen.com/subject/dnhsextx.html