电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

解析Android框架之Volley源碼

瀏覽:6日期:2022-09-18 11:08:11
目錄Volley簡單使用Volley執(zhí)行原理Volley簡單使用

我這里是以依賴架包的形式 ,大家也可以以gradle的形式進(jìn)行依賴。

解析Android框架之Volley源碼

好了,接下來上代碼了.....

//獲取volley的請(qǐng)求對(duì)象RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());StringRequest stringRequest = new StringRequest(StringRequest.Method.GET, 'http://www.baidu.com', new Response.Listener<String>() { @Override public void onResponse(String s) {Log.d('MainActivity', '----->' + s); }}, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) {Log.d('MainActivity', '---volleyError-->' + volleyError); }});requestQueue.add(stringRequest);

從代碼可以看出,首先newRequestQueue來獲取到一個(gè)請(qǐng)求隊(duì)列,然后在將StringRequest這個(gè)請(qǐng)求添加到請(qǐng)求隊(duì)列中,就可以了,就是這么簡單。當(dāng)然請(qǐng)求不值StringRequest,還有JsonObjectRequest ,ImageRequest等等但是用法都是一樣的,這里就不貼代碼了。Volley的簡單使用就這樣可以進(jìn)行請(qǐng)求了。是不是很簡單

Volley執(zhí)行原理

但是這個(gè)不是本篇的重點(diǎn),重點(diǎn)是分析一下這些是怎么執(zhí)行的。先上一張圖

解析Android框架之Volley源碼

我們先看看newRequestQueue這個(gè)內(nèi)部是怎么執(zhí)行的,代碼一開始連續(xù)執(zhí)行了幾個(gè)重載方法,最后走到newRequestQueue

public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) { 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 var7) {; } //這里進(jìn)行了一個(gè)版本的判斷 2.3之前用的是HTTPClient,2.3之后使用的是HttpURLConnection 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; if (maxDiskCacheBytes <= -1) {queue = new RequestQueue(new DiskBasedCache(cacheDir), network); } else {queue = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network); } queue.start(); return queue;}

在這里,我們看到了一個(gè)版本判斷,是不是瞬間感覺有點(diǎn)熟悉,沒錯(cuò),我們前面說的,volley2.3之前用的是HTTPClient,2.3之后使用的是HttpURLConnection就是在這里進(jìn)行判斷的。接著看queue.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();} }

mCacheDispatcher是緩存調(diào)度線程,NetworkDispatcher是網(wǎng)絡(luò)調(diào)度線程,而這個(gè)this.mDispatchers.length系統(tǒng)默認(rèn)的大小為4,也就是說,在這里總共啟動(dòng)了5個(gè)線程在后臺(tái)運(yùn)行。

好了,到這里,就可以了,看源碼不要每一行都弄懂,不然,出不來了。到這里就拿到了這個(gè)RequestQueue對(duì)象。回過頭來看前面使用的代碼

//獲取volley的請(qǐng)求對(duì)象RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());StringRequest stringRequest = new StringRequest(StringRequest.Method.GET, 'http://www.baidu.com', new Response.Listener<String>() { @Override public void onResponse(String s) {Log.d('MainActivity', '----->' + s); }}, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) {Log.d('MainActivity', '---volleyError-->' + volleyError); }});requestQueue.add(stringRequest);

我們拿到這個(gè)RequestQueue對(duì)象以后,然后就把這個(gè)請(qǐng)求通過add方法添加到隊(duì)列中,我們看看這個(gè)add()方法是怎么執(zhí)行的。

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 var7 = this.mWaitingRequests; synchronized(this.mWaitingRequests) {String cacheKey = request.getCacheKey();if (this.mWaitingRequests.containsKey(cacheKey)) { //判斷之前是否執(zhí)行過,但是還沒有返回結(jié)果 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 {//沒有的話就將請(qǐng)求加入緩存隊(duì)列mCacheQueue,同時(shí)加入mWaitingRequests中用來做下次同樣請(qǐng)求來時(shí)的重復(fù)判斷依據(jù) this.mWaitingRequests.put(cacheKey, (Object)null); this.mCacheQueue.add(request);}return request; }} }

從代碼中可以看出,首先判斷是否可以緩存,當(dāng)然,默認(rèn)是可以緩存的。如果不能緩存的話,則通過this.mNetworkQueue.add(request);將請(qǐng)求添加到網(wǎng)絡(luò)請(qǐng)求隊(duì)列中。如果可以緩存,則還會(huì)判斷一次這個(gè)請(qǐng)求是否請(qǐng)求,如果執(zhí)行過就就通過this.mWaitingRequests.put(cacheKey, stagedRequests);添加到mWaitingRequests隊(duì)列,不在重復(fù)請(qǐng)求。否則就加入到緩存隊(duì)列。

大體的流程是這樣。現(xiàn)在我們看看緩存的,和網(wǎng)絡(luò)的是怎么執(zhí)行的。我們找到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,找到run()方法

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 { while(true) {final Request<?> request = (Request)this.mCacheQueue.take(); //從緩存隊(duì)列中獲取到一個(gè)請(qǐng)求request.addMarker('cache-queue-take');if (request.isCanceled()) { //判斷請(qǐng)求是否取消,如果取消了,那就將該請(qǐng)求finish掉 request.finish('cache-discard-canceled');} else { Entry entry = this.mCache.get(request.getCacheKey()); if (entry == null) {//如果從緩存中取出來的內(nèi)容為空,則將請(qǐng)求加入到網(wǎng)絡(luò)線程中再次請(qǐng)求request.addMarker('cache-miss');this.mNetworkQueue.put(request); } else if (entry.isExpired()) { //如果請(qǐng)求過期了,則將請(qǐng)求加入到網(wǎng)絡(luò)線程中再次請(qǐng)求request.addMarker('cache-hit-expired');request.setCacheEntry(entry);this.mNetworkQueue.put(request); } else { //將數(shù)據(jù)回調(diào)到主線程request.addMarker('cache-hit');Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));request.addMarker('cache-hit-parsed');if (entry.refreshNeeded()) { 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 { this.mDelivery.postResponse(request, response);} }} }} catch (InterruptedException var4) { if (this.mQuit) {return; }} }} }} }

這里嵌套了幾個(gè)循環(huán),有點(diǎn)凌亂啊,但是慢慢分析的話,就會(huì)發(fā)現(xiàn),其實(shí)很清晰。我在注釋上面寫了,這里就不重復(fù)了

我們?cè)诳纯碞etworkDispatcher,看看網(wǎng)絡(luò)線程是怎么執(zhí)行的。一樣找到run()方法

public void run() {Process.setThreadPriority(10);while(true) { long startTimeMs; Request request; while(true) {startTimeMs = SystemClock.elapsedRealtime();try { request = (Request)this.mQueue.take(); //獲取到一個(gè)請(qǐng)求 break;} catch (InterruptedException var6) { if (this.mQuit) {return; }} } try {request.addMarker('network-queue-take');if (request.isCanceled()) { //如果請(qǐng)求取消了,則將請(qǐng)求finish掉 request.finish('network-discard-cancelled');} else {//進(jìn)行網(wǎng)絡(luò)請(qǐng)求 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 var7) {var7.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);this.parseAndDeliverNetworkError(request, var7); } catch (Exception var8) {VolleyLog.e(var8, 'Unhandled exception %s', new Object[]{var8.toString()});VolleyError volleyError = new VolleyError(var8);volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);this.mDelivery.postError(request, volleyError); }} }

代碼比較多,我們直接找到NetworkResponse networkResponse = this.mNetwork.performRequest(request);這句代碼,這句代碼就是請(qǐng)求網(wǎng)絡(luò)的代碼,最核心的。performRequest是一個(gè)接口,我們看看這個(gè)performRequest()方法。Network在最開始說版本判斷的時(shí)候里面有一句代碼Network network = new BasicNetwork((HttpStack)stack); 從這句代碼,我們可以知道BasicNetwork才是最終實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求的類,我們找到performRequest方法

public NetworkResponse performRequest(Request<?> request) throws VolleyError {long requestStart = SystemClock.elapsedRealtime();while(true) { HttpResponse httpResponse = null; byte[] responseContents = null; Map responseHeaders = Collections.emptyMap(); try {Map<String, String> headers = new HashMap();this.addCacheHeaders(headers, request.getCacheEntry());httpResponse = this.mHttpStack.performRequest(request, headers);StatusLine statusLine = httpResponse.getStatusLine();int statusCode = statusLine.getStatusCode();responseHeaders = convertHeaders(httpResponse.getAllHeaders());if (statusCode == 304) { Entry entry = request.getCacheEntry(); if (entry == null) {return new NetworkResponse(304, (byte[])null, responseHeaders, true, SystemClock.elapsedRealtime() - requestStart); } entry.responseHeaders.putAll(responseHeaders); return new NetworkResponse(304, entry.data, entry.responseHeaders, true, SystemClock.elapsedRealtime() - requestStart);}if (statusCode == 301 || statusCode == 302) { String newUrl = (String)responseHeaders.get('Location'); request.setRedirectUrl(newUrl);}byte[] responseContents;if (httpResponse.getEntity() != null) { responseContents = this.entityToBytes(httpResponse.getEntity());} else { responseContents = new byte[0];}long requestLifetime = SystemClock.elapsedRealtime() - requestStart;this.logSlowRequests(requestLifetime, request, responseContents, statusLine);if (statusCode >= 200 && statusCode <= 299) { return new NetworkResponse(statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);}throw new IOException(); } catch (SocketTimeoutException var12) {attemptRetryOnException('socket', request, new TimeoutError()); } catch (ConnectTimeoutException var13) {attemptRetryOnException('connection', request, new TimeoutError()); } catch (MalformedURLException var14) {throw new RuntimeException('Bad URL ' + request.getUrl(), var14); } catch (IOException var15) {int statusCode = false;NetworkResponse networkResponse = null;if (httpResponse == null) { throw new NoConnectionError(var15);}int statusCode = httpResponse.getStatusLine().getStatusCode();if (statusCode != 301 && statusCode != 302) { VolleyLog.e('Unexpected response code %d for %s', new Object[]{statusCode, request.getUrl()});} else { VolleyLog.e('Request at %s has been redirected to %s', new Object[]{request.getOriginUrl(), request.getUrl()});}if (responseContents == null) { throw new NetworkError(networkResponse);}networkResponse = new NetworkResponse(statusCode, (byte[])responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);if (statusCode != 401 && statusCode != 403) { if (statusCode != 301 && statusCode != 302) {throw new ServerError(networkResponse); } attemptRetryOnException('redirect', request, new AuthFailureError(networkResponse));} else { attemptRetryOnException('auth', request, new AuthFailureError(networkResponse));} }} }

代碼比較多,但是大多數(shù)代碼是判斷狀態(tài)返回碼的,不需要理會(huì)。

我們直接看httpResponse = this.mHttpStack.performRequest(request, headers);這一句代碼,HttpStack這個(gè)有沒有很熟悉。沒有??沒關(guān)系我在復(fù)制一次代碼

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

還是在這個(gè)版本判斷這里,這里就是HurlStack就是真正的網(wǎng)絡(luò)請(qǐng)求的類了,網(wǎng)絡(luò)請(qǐng)求,就是寫在這個(gè)類里面的。好了,volley整個(gè)流程大概就是這樣了。現(xiàn)在大家回過頭看最初的哪一張圖,是不是明了很多。

以上就是解析Android框架之Volley源碼的詳細(xì)內(nèi)容,更多關(guān)于Android框架之Volley源碼的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Android
相關(guān)文章:
主站蜘蛛池模板: 北京环球北美考试院【官方网站】|北京托福培训班|北京托福培训 | 气体检测仪-氢气检测仪-可燃气体传感器-恶臭电子鼻-深国安电子 | 电脑知识|软件|系统|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网 | 全温度恒温培养摇床-大容量-立式-远红外二氧化碳培养箱|南荣百科 | 卫浴散热器,卫浴暖气片,卫生间背篓暖气片,华圣格浴室暖气片 | 翻斗式矿车|固定式矿车|曲轨侧卸式矿车|梭式矿车|矿车配件-山东卓力矿车生产厂家 | 医院专用门厂家报价-医用病房门尺寸大全-抗菌木门品牌推荐 | 铝镁锰板_铝镁锰合金板_铝镁锰板厂家_铝镁锰金属屋面板_安徽建科 | 半容积式换热器_北京浮动盘管换热器厂家|北京亿丰上达 | 二维运动混料机,加热型混料机,干粉混料机-南京腾阳干燥设备厂 | 123悬赏网_发布悬赏任务_广告任务平台| 海尔生物医疗四川代理商,海尔低温冰箱四川销售-成都壹科医疗器械有限公司 | 西安文都考研官网_西安考研辅导班_考研培训机构_西安在职考研培训 | 微型驱动系统解决方案-深圳市兆威机电股份有限公司 | 我爱古诗词_古诗词名句赏析学习平台 | SPC工作站-连杆综合检具-表盘气动量仪-内孔缺陷检测仪-杭州朗多检测仪器有限公司 | 品牌广告服务平台,好排名,好流量,好生意。 | 代办建筑资质升级-建筑资质延期就找上海国信启航 | 活动策划,舞台搭建,活动策划公司-首选美湖上海活动策划公司 | 河南生物显微镜,全自动冰冻切片机-河南荣程联合科技有限公司 | 工业硝酸钠,硝酸钠厂家-淄博「文海工贸」 | 灌装封尾机_胶水灌装机_软管灌装封尾机_无锡和博自动化机械制造有限公司 | 磁粉制动器|张力控制器|气胀轴|伺服纠偏控制器整套厂家--台灵机电官网 | [品牌官网]贵州遵义双宁口腔连锁_贵州遵义牙科医院哪家好_种植牙_牙齿矫正_原华美口腔 | 煤矿支护网片_矿用勾花菱形网_缝管式_管缝式锚杆-邯郸市永年区志涛工矿配件有限公司 | 高压负荷开关-苏州雷尔沃电器有限公司 | 昆山PCB加工_SMT贴片_PCB抄板_线路板焊接加工-昆山腾宸电子科技有限公司 | 光栅尺厂家_数显表维修-苏州泽升精密机械 | 长沙广告公司|长沙广告制作设计|长沙led灯箱招牌制作找望城湖南锦蓝广告装饰工程有限公司 | 沈阳真空机_沈阳真空包装机_沈阳大米真空包装机-沈阳海鹞真空包装机械有限公司 | 防渗膜厂家|养殖防渗膜|水产养殖防渗膜-泰安佳路通工程材料有限公司 | 广州网站建设_小程序开发_番禺网站建设_佛山网站建设_粤联网络 | 优秀的临床医学知识库,临床知识库,医疗知识库,满足电子病历四级要求,免费试用 | 多米诺-多米诺世界纪录团队-多米诺世界-多米诺团队培训-多米诺公关活动-多米诺创意广告-多米诺大型表演-多米诺专业赛事 | 车充外壳,车载充电器外壳,车载点烟器外壳,点烟器连接头,旅行充充电器外壳,手机充电器外壳,深圳市华科达塑胶五金有限公司 | 大型低温冷却液循环泵-低温水槽冷阱「厂家品牌」京华仪器_京华仪器 | 知名电动蝶阀,电动球阀,气动蝶阀,气动球阀生产厂家|价格透明-【固菲阀门官网】 | 压缩空气冷冻式干燥机_吸附式干燥机_吸干机_沪盛冷干机 | 本安接线盒-本安电路用接线盒-本安分线盒-矿用电话接线盒-JHH生产厂家-宁波龙亿电子科技有限公司 | 油液红外光谱仪-油液监测系统-燃油嗅探仪-上海冉超光电科技有限公司 | 六自由度平台_六自由度运动平台_三自由度摇摆台—南京全控科技 |