安卓-网络

网络

OKHttp中body().string()其中string()只能被使用一次,使用过后就会被清空掉。即代码中调用两次body().string()的话第二次是没有值的。如果想要则需要用个临时变量保存起来。

Regrofit

OkHttpClickent配置超时时间

默认情况下,Retrofit的默认超时时间如下:

  • Connection timeout:10秒
  • Read timeout:10秒
  • Write timeout:10秒
  • Call timeout:0秒(代表没有超时)

如何设置超时时间

1
2
3
4
5
6
7
8
9
10
11
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.callTimeout(2, TimeUnit.MINUTES)
.build();

Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://10.0.2.2:3000/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create());

Connection Timeout-连接超时

connectionTimeout:从客户端发出一个请求开始到客户端与服务器端完成TCP的3次握手建立连接的这段时间。即,如果Retrofit在指定的时间无法与服务器端建立连接,那么Retrofit就认为此次请求失败。

比如,当你的用户可能会在网络状态不佳的情况下与你的服务器进行通信,那么你需要将增大这个数字。

Read Timeout-读取超时

readTimeout:从连接建立成功开始,Retrofit就会监测每个字节的数据传输的速率。如果其中某字节距离上一个字节传输成功的时间大于指定的readTimeout了,Retrofit就会认为这个请求是失败的。这个时间计数器会在读取到每个byte之后归零重新开始计时。所以如果你的响应当中有120个bytes需要传输到客户端,而每个byte的传输都需要5秒,这种情况下尽管完全传输需要600秒,但不会触发readTimeout(30秒)error

另外,readTimeout的触发不仅限于服务器端的处理能力,也有可能是糟糕的网络状态引起。

注意这个并不是说在指定的时间(比如30秒)内需要把响应内容完全接收,而是指相邻的两个字节之间的接收时间不能超过指定的时间(30秒)。

Write Timeout-写入超时

writeTimeout:跟readTimeout相对应的反方向的数据传输。它检查的是客户端向服务器端发送数据的速率。当然,跟readTimeout的计时器类似,每个byte发送成功之后这个计时器都会被重置。如果某个byte的数据传输时间 超过了配置的写入超时时间,Retrofit就会认为这个请求是失败的。

注意这个并不是说在指定时间(比如15秒)内需要把所有的数据都发送到服务器端,而是指相邻的两个字节之间的发送时间不能超过指定的时间(15秒)。

Call Timeout-请求超时

可从这看 https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/-builder/call-timeout/

CallTimeout的计时器横跨整个请求,从DNS解析,连接建立,发送数据到服务器,服务器端处理,然后发送响应到客户端,直到客户端完全读取响应内容。如果这个请求需要重定向或重试,这些过程都必须在指定的callTimeout时间区间内完成。如果不能完成Retrofit就会认为请求失败。

CallTimeout=0:代表不考虑请求的超时

当你的应用需要限定App在某个指定的时间内得到响应结果,如果在指定时间内未能得到就认为是超时的话,那么你应该用callTimeout

网络相关问题

java.lang.RuntimeException: Parcel: unable to marshal value

接口回调传递参数丢失问题

原因:

  1. 在继承Parcel类中,需要读或写其他自定义类数据,这些自定义类数据需要实现Serializable序列化接口
  2. 在继承Serializabel类中,需要读或写其他自定义类,这些自定义类数据含有的对象类没有继承Serializable接口