case Request.Method.HEAD:
builder.head();
break;
case Request.Method.OPTIONS:
builder.method("OPTIONS", null);
break;
case Request.Method.TRACE:
builder.method("TRACE", null);
break;
case Request.Method.PATCH:
builder.patch(createRequestBody(request));
break;
default:
throw new IllegalStateException("Unknown method type.");
}
}
private static RequestBody createRequestBody(Request request) throws AuthFailureError {
final byte[] body = request.getBody();
if (body == null) return null;
return RequestBody.create(MediaType.parse(request.getBodyContentType()), body);
}
private static ProtocolVersion parseProtocol(final Protocol protocol) {
switch (protocol) {
case HTTP_1_0:
return new ProtocolVersion("HTTP", 1, 0);
case HTTP_1_1:
return new ProtocolVersion("HTTP", 1, 1);
case SPDY_3:
return new ProtocolVersion("SPDY", 3, 1);
case HTTP_2:
return new ProtocolVersion("HTTP", 2, 0);
}
throw new IllegalAccessError("Unkwown protocol");
}
@Override
public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
throws IOException, AuthFailureError {
int timeoutMs = request.getTimeoutMs();
OkHttpClient client = mClient.newBuilder()
.readTimeout(timeoutMs, TimeUnit.MILLISECONDS)
.connectTimeout(timeoutMs, TimeUnit.MILLISECONDS)
.writeTimeout(timeoutMs, TimeUnit.MILLISECONDS)
.build();
okhttp3.Request.Builder okHttpRequestBuilder = new okhttp3.Request.Builder();
Map<String, String> headers = request.getHeaders();
for (final String name : headers.keySet()) {
okHttpRequestBuilder.addHeader(name, headers.get(name));
}
for (final String name : additionalHeaders.keySet()) {
okHttpRequestBuilder.addHeader(name, additionalHeaders.get(name));
}
setConnectionParametersForRequest(okHttpRequestBuilder, request);
okhttp3.Request okhttp3Request = okHttpRequestBuilder.url(request.getUrl()).build();
Response okHttpResponse = client.newCall(okhttp3Request).execute();
StatusLine responseStatus = new BasicStatusLine
(
parseProtocol(okHttpResponse.protocol()),
okHttpResponse.code(),
okHttpResponse.message()
);
BasicHttpResponse response = new BasicHttpResponse(responseStatus);
response.setEntity(entityFromOkHttpResponse(okHttpResponse));
Headers responseHeaders = okHttpResponse.headers();
for (int i = 0, len = responseHeaders.size(); i < len; i++) {
final String name = responseHeaders.name(i), value = responseHeaders.value(i);
if (name != null) {
response.addHeader(new BasicHeader(name, value));
}
}
return response;
}
}
3、创建Volley队列RequestQueue
RequestQueue requestQueue = Volley.newRequestQueue(this, new OkHttpStack(new OkHttpClient()));
二、Volley是Google官方发布的异步网络请求框架,试用场景数据量小,通信频繁的网络操作。Volley 异步网络请求分析:
![这里写图片描述](https://img-blog.csdn.net/20160110195407702)
上图是官方给出的Volley架构图,蓝色为主线程,绿色为缓存线程,橙色是网络线程。总的来说,就是一个请求队列和三种线程,UI线程(1个),Cache线程(1个)和Network线程(默认是4个)。
1、UI线程负责添加请求任务,执行任务结果;
2、Cache线程负责检查缓存,命中后直接将任务结果分发到主线程;
3、Network线程由多个任务线程(NetworkDispatcher)组成的,相当于一个大小为size的线程池,这些线程会同时启动,并持续的从任务队列中获取待执行的任务,任务执行完后会将结果分发到UI线程。
4、Request:请求的抽象类。StringRequest、JsonRequest、ImageRequest 都是它的子类,表示某种类型的请求。可扩展性强。
5、RequestQueue.java:请求队列,里面包含一个CacheDispatcher(用于处理走缓存请求的调度线程)、NetworkDispatcher数组(用于处理走网络请求的调度线程),一个ResponseDelivery(返回结果分发接口),通过 start() 方法启动时会启动CacheDispatcher和NetworkDispatchers。然后看创建请求队列方法内的代码:
public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) {
File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
String userAgent = "volley/0";
try {
String packageName = context.getPackageName();
PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
userAgent = packageName + "/" + info.versionCode;
} catch (NameNotFoundException e) {
}
if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
// Prior to Gingerbread, HttpUrlConnection was unreliable.
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
Network network = new BasicNetwork(stack);
RequestQueue queue;
if (maxDiskCacheBytes <= -1)
{
// No maximum size specified
queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
}
else
{
// Disk cache size specified
queue = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network);
}
queue.start();
return queue;
}
看到这里,需要了解三个类的作用:
HttpStack.java:处理HTTP请求,返回请求结果。目前Volley中有基于 HttpURLConnection 的 HurlStack 和 基于 Apache HttpClient 的HttpClientStack。
Network.java:调用HttpStack处理请求,并将结果转换为可被ResponseDelivery处理的NetworkResponse。
Cache.java:缓存请求结果,Volley默认使用的是基于sdcard缓存的DiskBasedCache。NetworkDispatcher得到请求结果后判断是否需要存储在 Cache,CacheDispatcher会从 Cache 中取缓存结果。
创建Network需要HttpStatck,如果newRequestQueue传入的stack为null,API Level >= 9,采用基于 HttpURLConnection 的 HurlStack;小于 9,采用基于 HttpClient 的 HttpClientStack。
if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
// Prior to Gingerbread, HttpUrlConnection was unreliable.
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
接下来启动所需的所有线程:
public void start() {
stop(); // Make sure any currently running dispatchers are stopped.
// Create the cache dispatcher and start it.
mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
mCacheDispatcher.start();
// Create network dispatchers (and corresponding threads) up to the pool size.
for (int i = 0; i < mDispatchers.length; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}
CacheDispatcher.java:继承自Thread,用于调度处理「缓存请求」。启动后会不断从缓存请求队列中取请求处理,队列为空则等待,请求处理结束则将结果传递给ResponseDelivery去执行后续处理。当结果未缓存过、缓存失效或缓存需要刷新的情况下,该请求都需要重新进入NetworkDispatcher去调度处理。
NetworkDispatcher.java:继承自Thread,用于调度处理「网络请求」。启动后会不断从网络请求队列中取请求处理,队列为空则等待,请求处理结束则将结果传递给ResponseDelivery去执行后续处理,并判断结果是否要进行缓存。
ResponseDelivery.java:分发结果的interface,postResponse以及postError。
接下来再回头看一下Volley的架构图。
第一步:把请求加入缓存队列
第二步:「缓存调度线程」CacheDispatcher从缓存队列中取出一个请求,如果缓存命中,就读取缓存响应并解析,然后将结果返回到主线程
第三步:缓存未命中,请求被加入网络请求队列,「网络调度线程」NetworkDispatcher轮询取出请求,HTTP请求传输,解析响应,写入缓存,然后将结果返回到主线程
总结:
在主线程中调用RequestQueue的add()方法来添加一个网络请求任务。
1、以请求方法(GET、POST、PUT…) + URL作为缓存KEY,根据cacheKey从缓存队列里获取该网络请求任务。
a、如果为空的话则把这个任务加入到网络请求队列中;
b、如果不为空的话再判断该缓存是否已过期,如果已经过期了则同样把这个任务 加入到网络请求队列中;
c、否则就认为不需要重发网络请求,直接使用缓存中的数据即可。
2、加入到网络请求队列中的任务
a、发送HTTP请求
b、解析响应结果,写入缓存,并回调主线程。
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/263321a4b97cfcc12e95a253b09deea3.png)
![img](https://img-blog.csdnimg.cn/img_convert/54078e6afc05ecb568e4e96ead28d2c8.png)
![img](https://img-blog.csdnimg.cn/img_convert/14d89a415858f9ae645c2c062e296994.png)
![img](https://img-blog.csdnimg.cn/img_convert/a790c1dc6534349d197336a6eb98a838.png)
![img](https://img-blog.csdnimg.cn/img_convert/bd044fd27aed057cc71f8e23a82869b5.png)
![img](https://img-blog.csdnimg.cn/img_convert/99d5abcc7c381d51c967a3dc7c7a3c52.png)
![img](https://img-blog.csdnimg.cn/13f2cb2e05a14868a3f0fd6ac81d625c.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)**
![img](https://img-blog.csdnimg.cn/img_convert/e1554426c25981fc0e82f57bf42d46be.png)
最后,如果大伙有什么好的学习方法或建议欢迎大家在评论中积极留言哈,希望大家能够共同学习、共同努力、共同进步。
**小编在这里祝小伙伴们在未来的日子里都可以 升职加薪,当上总经理,出任CEO,迎娶白富美,走上人生巅峰!!**
> 不论遇到什么困难,都不应该成为我们放弃的理由!
很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从那里入手去学习
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言,一定会认真查询,修正不足,谢谢。
**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
![img](https://img-blog.csdnimg.cn/img_convert/4a2473c384afb51d95ff3352c1749f08.png)
[外链图片转存中...(img-JvrxGh0D-1712892076889)]
最后,如果大伙有什么好的学习方法或建议欢迎大家在评论中积极留言哈,希望大家能够共同学习、共同努力、共同进步。
**小编在这里祝小伙伴们在未来的日子里都可以 升职加薪,当上总经理,出任CEO,迎娶白富美,走上人生巅峰!!**
> 不论遇到什么困难,都不应该成为我们放弃的理由!
很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从那里入手去学习
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言,一定会认真查询,修正不足,谢谢。
**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
[外链图片转存中...(img-WT8olpTi-1712892076890)]