2024年安卓最全腾讯面试被怼得体无完肤,OkHttp都不会,凭什么拿offer!,2024年最新阿里p8面试官

自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

List headerStrings=response.headers(“Vary”);

Log.i(TAG,headerString);
Iterator it=headerStrings.iterator();
while (it.hasNext()) {
Log.i(TAG,it.next());
}

Post提交String

以下例子使用https://reqres.in测试请求:

private static final MediaType JSON = MediaType.parse(“application/json; charset=utf-8”);

String url = “https://reqres.in/api/users/”;
String jsonString = “{\n” +
" “name”: “morpheus”,\n" +
" “job”: “leader”\n" +
“}”;

private void post(String url, final String requestString) {
RequestBody requestBody = RequestBody.create(JSON, requestString);

Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();

mClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
call.cancel();
}

@Override
public void onResponse(Call call, Response response) throws IOException {
final String responseString = response.body().string();
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
mTextView.setText(responseString);
}
});
}
});
}

Post提交表单

final String url = “https://tieba.baidu.com/f”;

RequestBody requestBody = new FormBody.Builder()
.add(“ie”, “utf-8”)
.add(“kw”, “minecraft”)
.build();

Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();

Post提交文件

public static final MediaType JPEG = MediaType.parse(“image/jpeg”);

File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM), “building.jpg”);

RequestBody requestBody = RequestBody.create(JPEG, file);

Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();

Post提交流

RequestBody requestBody = new RequestBody() {
@Nullable
@Override
public MediaType contentType() {
return null;
}

@Override
public void writeTo(@NotNull BufferedSink bufferedSink) throws IOException {
bufferedSink.writeUtf8(requestString);
}
};

Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();

使用Gson解析response

String url = “https://api.github.com/gists/c2a7c39532239ff261be”;

class Gist{
Map<String,GistFile> files;
}

class GistFile{
String content;
}

Gson gson = new Gson();
Gist gist = gson.fromJson(response.body().charStream(),Gist.class);
for(Map.Entry<String,GistFile> entry:gist.files.entrySet()){
Log.i(TAG,entry.getKey()+ " "+entry.getValue().content);
}

设置超时

OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(3, TimeUnit.SECONDS)
.build();

配置新client

.newBuilder()会返回一个配置相同的buidler

OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(3, TimeUnit.SECONDS)
.build();

OkHttpClient client2 = client.newBuilder()
.connectTimeout(5, TimeUnit.SECONDS)
.build();

拦截器

拦截器(Interceptor)是OkHttp的概念,也是核心功能。OkHttp有两种拦截器,分别是应用拦截器和网络拦截器。拦截器的主要目的在于重写requestresponse,可以在发出request前修改headers或body,也可以在收到response前修改headers或body。我们完全可以在用户收到reponse前将其修改成一个完全不一样的新response,这一功能使得我们可以进行后续的缓存策略修改或是使用gzip压缩requestBody等操作。应用拦截器在用户发出一次请求后的全过程中仅调用一次,而网络拦截器可能因为重定向等问题多次调用,例如有一次重定向就会调用两次。拦截器可以设置多个,并按添加顺序进行拦截。下图来自OkHttp文档:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

两种拦截器区别如下,参考OkHttp文档原文:

Application interceptors

  • Don’t need to worry about intermediate responses like redirects and retries.
  • Are always invoked once, even if the HTTP response is served from the cache.
  • Observe the application’s original intent. Unconcerned with OkHttp-injected headers like If-None-Match.
  • Permitted to short-circuit and not call Chain.proceed().
  • Permitted to retry and make multiple calls to Chain.proceed().
  • Can adjust Call timeouts using withConnectTimeout, withReadTimeout,withWriteTimeout.

Network Interceptors

  • Able to operate on intermediate responses like redirects and retries.
  • Not invoked for cached responses that short-circuit the network.
  • Observe the data just as it will be transmitted over the network.
  • Access to the Connection that carries the request.

个人翻译如下:

应用拦截器

  • 使用时不需要考虑例如重定向、重试等中转请求带来的影响
  • 全过程只拦截一次,即使拦截的response来自缓存
  • 可处理来自Applcation(参考拦截器图解)的本意。(例如no-cache)不涉及OkHttp的头部注入例如If-None-Match头部(这是在core注入的)
  • 可以不调用Chain.proceed()(例如return一个来自缓存的response,但不能return null
  • 可以重试和多次调用Chain.proceed()
  • 可通过withConnectTimeout,withReadTimeout, withWriteTimeout调整Call的超时时间.

网络拦截器

  • 可处理例如重定向、重试等中转请求
  • 不涉及缓存的调用
  • 可处理来自服务器的原始响应
  • 可对最终发出前的请求做读写
  • 实现拦截器

以上所说拦截器可对处于中间时期的requestresponse做修改,就是在chain.proceed(request)的前后完成的。
chain.proceed(request)会返回通过core或服务器处理后得到的response,这个方法会阻塞线程。

String url = “http://publicobject.com/helloworld.txt”;

class LoggingInterceptor implements Interceptor {
@Override public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();

//do something to rewrite request

long t1 = System.nanoTime();
Log.i(TAG,String.format(“Sending request %s on %s%n%s”,
request.url(), chain.connection(), request.headers()));

Response response = chain.proceed(request);

long t2 = System.nanoTime();
Log.i(TAG,String.format(“Received response for %s in %.1fms%n%s”,
response.request().url(), (t2 - t1) / 1e6d, response.headers()));

//do something to rewrite response

return response;
}
}

  • 设置应用拦截器

两种拦截器在实现的时候没有区别,充当那种拦截器取决于调用的方法是.addInterceptor()或是.addNetworkInterceptor().addInterceptor()表示设置应用拦截器,.addNetworkInterceptor()则是网络拦截器。

OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new LoggingInterceptor())
.build();

  • 设置网络拦截器

OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new LoggingInterceptor())
.build();

缓存处理

OkHttp默认不使用缓存,可以调用.cache()开启,但.cache()仅能设置缓存区大小和缓存读写的位置。Cache-Control头部是Http协议定义的,而OkHttp完全遵循Http协议,所以OkHttp的缓存策略是由请求头或响应头中的Cache-Control头部而定的。如果服务器返回的response已经带有Cache-Control响应头,在buidler中调用.cache()即可使用缓存。反之当收到的response没有设置Cache-Control时,可以在拦截器里手动添加,不同参数对应不同的缓存策略。不论response是否有Cache-Control,始终可以在发出request时添加例如Cache-control: no-cache来控制缓存使用与否。

启用缓存

String url = “http://publicobject.com/helloworld.txt”;

int _10MB = 10 * 1024 * 1024;
File cacheDir = getCacheDir();
Cache cache = new Cache(cacheDir, _10MB);

OkHttpClient client = new OkHttpClient.Builder()
.cache(cache)
.build();

缓存策略

Http协议的Cache-Control的参数有很多,可设置多个参数,多个参数间用逗号分隔开。以下主要介绍其中几种的含义

  • Cache-Control: max-age=3600
    设置缓存过期时间为一小时。单位为秒,用于response

  • Cache-Control: max-stale=3600
    表示接受使用过期的缓存,最长时间为过期后的一小时,单位为秒。用于request

  • Cache-control: no-cache
    先不使用本地缓存,向服务器验证缓存是否过期后决定缓存使用与否,且并不取消本次response的缓存。用于request

  • Cache-control: no-store
    本次请求不缓存得到的response,也表示本次请求不读取缓存。用于request

  • Cache-control: only-if-cached
    仅尝试使用缓存。用于request

  • Cache-control: public
    表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存,即使是通常不可缓存的内容。(例如该响应没有max-age指令或Expires消息头, 该响应对应的请求方法是 POST )

  • Cache-control: private
    表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。私有缓存可以缓存响应内容,比如:对应用户的本地浏览器。

  • Cache-Control: min-fresh=3600
    表示客户端希望获取一个能在指定的秒数内保持其最新状态的响应。

  • Cache-control: must-revalidate
    一旦资源过期(比如已经超过max-age),在成功向原始服务器验证之前,缓存不能用该资源响应后续请求。

此外与缓存有关的header可能还有ExpiresPragma,这里暂不介绍

  • 直接修改Cache-Control头部定义缓存策略

class CacheInterceptor implements Interceptor {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();

request = request.newBuilder()
.header(“Cache-Control”, “max-stale=3600”)
.build();

return chain.proceed(request);
}
}

Interceptor interceptor = new CacheInterceptor();

mClient = new OkHttpClient.Builder()
.cache(cache)
.addInterceptor(interceptor)
.build();

  • 使用CacheControl.Builder()定义缓存策略

CacheControl类只能在拦截器中使用,其实质只是在请求头或响应头为Cache-Control添加不同的参数而已,并没有其他作用

class ForceCacheInterceptor implements Interceptor {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();

CacheControl cacheControl = new CacheControl.Builder()
.onlyIfCached()
.build();

request = request.newBuilder()
.cacheControl(cacheControl)
.build();

return chain.proceed(request);
}
}

Interceptor interceptor = new ForceCacheInterceptor();

mClient = new OkHttpClient.Builder()
.cache(cache)
.addInterceptor(interceptor)
.build();

CacheControl.Builder的常用方法

  • .maxAge(3600, TimeUnit.SECONDS);
  • .maxStale(3600, TimeUnit.SECONDS);
  • .noCache();
  • .noStore();
  • .onlyIfCached();

含义参考Cache-Control参数介绍

  • 使用CacheControl的伴生对象定义缓存策略

CacheControl的伴生对象有两个,CacheControl.FORCE_CACHECacheControl.FORCE_NETWORK,分别表示强制使用缓存和强制使用网络。

public class ForceNetworkInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
if (!NetworkUtils.internetAvailable()) {
builder.cacheControl(CacheControl.FORCE_NETWORK);
}

return chain.proceed(builder.build());
}
}

分享读者

作者2013年java转到Android开发,在小厂待过,也去过华为,OPPO等大厂待过,18年四月份进了阿里一直到现在。

被人面试过,也面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长,而且极易碰到天花板技术停滞不前!

我们整理了一份阿里P7级别的Android架构师全套学习资料,特别适合有3-5年以上经验的小伙伴深入学习提升。

主要包括阿里,以及字节跳动,腾讯,华为,小米,等一线互联网公司主流架构技术。如果你有需要,尽管拿走好了。

35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

架构师全套学习资料,特别适合有3-5年以上经验的小伙伴深入学习提升。

主要包括阿里,以及字节跳动,腾讯,华为,小米,等一线互联网公司主流架构技术。如果你有需要,尽管拿走好了。

[外链图片转存中…(img-GnW9Enkx-1715005317261)]

35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值