Volley原理超级简单的

最近有点对源码上瘾。。。有点时间,都归纳一些,总结下

Volley使用方法,不写了,百度一堆。下包,依赖,使用

简单代码:

 public void getVolley(View view) {
        //第一步
        RequestQueue requestQueue = Volley.newRequestQueue(this);

        //第二步
        StringRequest stringRequest = new StringRequest("http://www.baidu.com", new Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                Log.e("TAG", "success : " + s);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.e("TAG", "fail : " + volleyError.toString());
            }
        });

        //第三步
        requestQueue.add(stringRequest);
    }

首先第一步,需要获取到一个RequestQueue对象

 public static RequestQueue newRequestQueue(Context context) {
        return newRequestQueue(context, (HttpStack)null);
    }

方法一个个追,没啥解释~ 

 public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        File cacheDir = new File(context.getCacheDir(), "volley");
        String userAgent = "volley/0";

        try {
            String packageName = context.getPackageName();
            PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
            userAgent = packageName + "/" + info.versionCode;
        } catch (NameNotFoundException var6) {
            ;
        }

        if(stack == null) {
            if(VERSION.SDK_INT >= 9) {
                stack = new HurlStack();
            } else {
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }

        Network network = new BasicNetwork((HttpStack)stack);
        RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
        queue.start();
        return queue;
    }

关键代码:

if(stack == null) {
            if(VERSION.SDK_INT >= 9) {
                stack = new HurlStack();
            } else {
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }

追进去看,可以发现,stack就是Volley对HttpClient和 HttpURLConnection 做的封装。

都会创建一个Network,根据stack来处理网络请求。

 Network network = new BasicNetwork((HttpStack)stack);
        RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
        queue.start();

创建Network后,new RequestQueue对象,start启动。开启请求队列,并返回请求队列。

 public void start() {
        this.stop();
        this.mCacheDispatcher = new CacheDispatcher(this.mCacheQueue, this.mNetworkQueue, this.mCache, this.mDelivery);
        this.mCacheDispatcher.start();

        for(int i = 0; i < this.mDispatchers.length; ++i) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(this.mNetworkQueue, this.mNetwork, this.mCache, this.mDelivery);
            this.mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }

    }
CacheDispatcher:缓存分发器
public class CacheDispatcher extends Thread

其实就是开启子线程的缓存请求队列。

 for(int i = 0; i < this.mDispatchers.length; ++i) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(this.mNetworkQueue, this.mNetwork, this.mCache, this.mDelivery);
            this.mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }

同理,可以理解就是开启子线程网络请求队列。

public class NetworkDispatcher extends Thread

整体框架基本就出来了,volley网络请求首先从缓存中读取是否有一份数据,如果有,缓存中读取,加快了读取速度。如果没有,走NetworkDispatcher网络读取数据。

现在来单独看看两个类,缓存以及网络

CacheDispatcher
public class CacheDispatcher extends Thread {
    private static final boolean DEBUG;
    private final BlockingQueue<Request<?>> mCacheQueue;
    private final BlockingQueue<Request<?>> mNetworkQueue;
    private final Cache mCache;
    private final ResponseDelivery mDelivery;
    private volatile boolean mQuit = false;

    public CacheDispatcher(BlockingQueue<Request<?>> cacheQueue, BlockingQueue<Request<?>> networkQueue, Cache cache, ResponseDelivery delivery) {
        this.mCacheQueue = cacheQueue;
        this.mNetworkQueue = networkQueue;
        this.mCache = cache;
        this.mDelivery = delivery;
    }

    public void quit() {
        this.mQuit = true;
        this.interrupt();
    }



    public void run() {
        if(DEBUG) {
            VolleyLog.v("start new dispatcher", new Object[0]);
        }

        Process.setThreadPriority(10);
        this.mCache.initialize();

        while(true) {
            while(true) {
                while(true) {
                    while(true) {
                        try {
                            final Request<?> request = (Request)this.mCacheQueue.take();
                            request.addMarker("cache-queue-take");
                            if(request.isCanceled()) {
                                request.finish("cache-discard-canceled");
                            } else {
                                Entry entry = this.mCache.get(request.getCacheKey());
                                if(entry == null) {
                                    request.addMarker("cache-miss");
                                    this.mNetworkQueue.put(request);
                                } else if(!entry.isExpired()) {
                                    request.addMarker("cache-hit");
                                    Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));
                                    request.addMarker("cache-hit-parsed");
                                    if(!entry.refreshNeeded()) {
                                        this.mDelivery.postResponse(request, response);
                                    } else {
                                        request.addMarker("cache-hit-refresh-needed");
                                        request.setCacheEntry(entry);
                                        response.intermediate = true;
                                        this.mDelivery.postResponse(request, response, new Runnable() {
                                            public void run() {
                                                try {
                                                    CacheDispatcher.this.mNetworkQueue.put(request);
                                                } catch (InterruptedException var2) {
                                                    ;
                                                }

                                            }
                                        });
                                    }
                                } else {
                                    request.addMarker("cache-hit-expired");
                                    request.setCacheEntry(entry);
                                    this.mNetworkQueue.put(request);
                                }
                            }
                        } catch (InterruptedException var4) {
                            if(this.mQuit) {
                                return;
                            }
                        }
                    }
                }
            }
        }
    }

    static {
        DEBUG = VolleyLog.DEBUG;
    }
}

注意,Thread 直接看run方法

一直while循环:

 Entry entry = this.mCache.get(request.getCacheKey());

缓存队列中获取缓存数据,判断是否为空,为空,添加到网络请求队列。

不为空:entry.isExpired()判断是否过期,过期,添加到网络请求队列,

不过期:

Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));

解析数据:entry.refreshNeeded(),判断是否需要刷新,需要刷新,添加到网络请求队列,不需要直接把结果回调出来。

完毕。

 

NetworkDispatcher.java
public class NetworkDispatcher extends Thread {
    private final BlockingQueue<Request<?>> mQueue;
    private final Network mNetwork;
    private final Cache mCache;
    private final ResponseDelivery mDelivery;
    private volatile boolean mQuit = false;

    public NetworkDispatcher(BlockingQueue<Request<?>> queue, Network network, Cache cache, ResponseDelivery delivery) {
        this.mQueue = queue;
        this.mNetwork = network;
        this.mCache = cache;
        this.mDelivery = delivery;
    }

    public void quit() {
        this.mQuit = true;
        this.interrupt();
    }

    @TargetApi(14)
    private void addTrafficStatsTag(Request<?> request) {
        if(VERSION.SDK_INT >= 14) {
            TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());
        }

    }

    public void run() {
        Process.setThreadPriority(10);

        while(true) {
            Request request;
            while(true) {
                try {
                    request = (Request)this.mQueue.take();
                    break;
                } catch (InterruptedException var4) {
                    if(this.mQuit) {
                        return;
                    }
                }
            }

            try {
                request.addMarker("network-queue-take");
                if(request.isCanceled()) {
                    request.finish("network-discard-cancelled");
                } else {
                    this.addTrafficStatsTag(request);
                    NetworkResponse networkResponse = this.mNetwork.performRequest(request);
                    request.addMarker("network-http-complete");
                    if(networkResponse.notModified && request.hasHadResponseDelivered()) {
                        request.finish("not-modified");
                    } else {
                        Response<?> response = request.parseNetworkResponse(networkResponse);
                        request.addMarker("network-parse-complete");
                        if(request.shouldCache() && response.cacheEntry != null) {
                            this.mCache.put(request.getCacheKey(), response.cacheEntry);
                            request.addMarker("network-cache-written");
                        }

                        request.markDelivered();
                        this.mDelivery.postResponse(request, response);
                    }
                }
            } catch (VolleyError var5) {
                this.parseAndDeliverNetworkError(request, var5);
            } catch (Exception var6) {
                VolleyLog.e(var6, "Unhandled exception %s", new Object[]{var6.toString()});
                this.mDelivery.postError(request, new VolleyError(var6));
            }
        }
    }

    private void parseAndDeliverNetworkError(Request<?> request, VolleyError error) {
        error = request.parseNetworkError(error);
        this.mDelivery.postError(request, error);
    }
}

run方法:继续while循环,网络请求不断运行

  NetworkResponse networkResponse = this.mNetwork.performRequest(request);

网络请求,performRequest发送请求。

 Response<?> response = request.parseNetworkResponse(networkResponse);

parseNetwordResponse解析数据

if(request.shouldCache() && response.cacheEntry != null) {
                            this.mCache.put(request.getCacheKey(), response.cacheEntry);
                            request.addMarker("network-cache-written");
                        }

这里可以看到,解析的数据会存一份到缓存当中。

数据都处理完,给ResponseDelivery ,它给处理

public interface ResponseDelivery {
    void postResponse(Request<?> var1, Response<?> var2);

    void postResponse(Request<?> var1, Response<?> var2, Runnable var3);

    void postError(Request<?> var1, VolleyError var2);
}

第二步:StringRequest  网络成功失败的回调

第三步add

 public <T> Request<T> add(Request<T> request) {
        request.setRequestQueue(this);
        Set var2 = this.mCurrentRequests;
        synchronized(this.mCurrentRequests) {
            this.mCurrentRequests.add(request);
        }

        request.setSequence(this.getSequenceNumber());
        request.addMarker("add-to-queue");
        if(!request.shouldCache()) {
            this.mNetworkQueue.add(request);
            return request;
        } else {
            Map var8 = this.mWaitingRequests;
            synchronized(this.mWaitingRequests) {
                String cacheKey = request.getCacheKey();
                if(this.mWaitingRequests.containsKey(cacheKey)) {
                    Queue<Request<?>> stagedRequests = (Queue)this.mWaitingRequests.get(cacheKey);
                    if(stagedRequests == null) {
                        stagedRequests = new LinkedList();
                    }

                    ((Queue)stagedRequests).add(request);
                    this.mWaitingRequests.put(cacheKey, stagedRequests);
                    if(VolleyLog.DEBUG) {
                        VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", new Object[]{cacheKey});
                    }
                } else {
                    this.mWaitingRequests.put(cacheKey, (Object)null);
                    this.mCacheQueue.add(request);
                }

                return request;
            }
        }
    }

消息添加到队列中,关键代码:

!request.shouldCache()

进行判断,当前请求是否可以缓存。如果不可以缓存,添加到网络请求队列,可以缓存,就添加到缓存请求队列。

 

总结:volley发送网络请求,开启两个请求队列,一个缓存请求队列,一个网络请求队列。先从缓存请求队列去检查是否过期,数据是否需要刷新呀,如果过期或者需要刷新,添加到网络队列进行网络请求,NetworkDispatcher处理,交给主线程回应。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值