学习资料:
在手机状态栏中,并没有流量和WIFI
联网的标志
1. 无网络,使用本地缓存
完整Activity代码:
public class NoNetworkActivity extends AppCompatActivity implements ResultCallback<String> {
private TextView tv_info;
private String cachePath;
private Platform mPlatform;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_no_network);
//缓存路径
String path = Environment.getExternalStorageDirectory().getPath()
+ File.separator + Strings.FILE_PATH + File.separator + Strings.CACHE_PATH;
File directory = new File(path);
if (!directory.exists()) {
if (directory.mkdirs()) ToastUtils.show(NoNetworkActivity.this, "缓存文件夹创建成功");
}
cachePath = directory.getPath();
init();
}
/**
* 初始化
*/
private void init() {
mPlatform = Platform.get();
tv_info = (TextView) findViewById(R.id.no_network_activity_tv);
request();
}
private void request() {
OkHttpClient okHttpClient = new OkHttpClient
.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.addNetworkInterceptor(new Interceptor() {//添加网络拦截器
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
if (isNetworkConnected()) {
int maxAge = 60 * 60;// 有网 就1个小时可用
return response.newBuilder()
.header("Cache-Control", "public, max-age=" + maxAge)
.build();
} else {
int maxStale = 60 * 60 * 24 * 7;// 没网 就1周可用
return response.newBuilder()
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.build();
}
}
})
.cache(new Cache(new File(cachePath), 30 * 1024 * 1024))//最大 30m
.build();
Request request = new Request.Builder().url(Urls.GET_URL).build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
sendFailResultCallback(e);//失败回调
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//请求结果
ResponseBody responseBody = null;
try {
//判断请求是否取消
if (call.isCanceled()) {
sendFailResultCallback(new IOException("Request Canceled"));
return;
}
//获取请求结果 ResponseBody
responseBody = response.body();
//获取字符串
String json = responseBody.string();
Log.e("activity", json);
//成功回调
sendSuccessResultCallback(json);
} catch (Exception e) {//发生异常,失败回调
sendFailResultCallback(e);
} finally {//记得关闭操作
if (null != responseBody) {
responseBody.close();
}
}
}
});
}
/**
* 手机是否联网
*/
private boolean isNetworkConnected() {
//6.0 之后得使用 getApplicationContext()..getSystemService(...)
//否则会内存泄漏
ConnectivityManager manager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = manager.getActiveNetworkInfo();
return activeNetworkInfo.isConnected();
}
/**
* 网络请求失败
*/
@Override
public void sendFailResultCallback(final Exception e) {
doSomething(new Runnable() {
@Override
public void run() {
String info = "Fail Message --> " + e.getMessage();
tv_info.setText(info);
}
});
}
/**
* 请求成功
*/
@Override
public void sendSuccessResultCallback(final String result) {
doSomething(new Runnable() {
@Override
public void run() {
tv_info.setText(JsonFormatUtils.formatJson(result));
}
});
}
/**
* UI线程回调
*/
private void doSomething(Runnable runnable) {
mPlatform.execute(runnable);
}
}
cache(Cache,Size)
:添加缓存,指定缓存路径和空间大小
当设备断网时,通过Interceptor
拦截器来进行网络访问,可以直接读取之前本地缓存
使用addNetworkInterceptor(Interceptor)
为OkHttpCLient
添加一个网络拦截器
重写Interceptor
内的intercept(Chain)
方法,根据网络状态,设置缓存有效期
-
Cache-Control
,缓存控制 -
public
,所有网页信息都缓存 -
max-age
,缓存有效期限,在这个期限内,不去再去进行网络访问 -
only-if-cached
,只接受缓存的内容 -
max-stale
,在设置期限内,客户端可以接受过去的内容
百度百科中Cache-control说得挺简单明了
2. Interceptor拦截器
Interceptor
是一个接口
源码:
/*
* Copyright (C) 2014 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3;
import java.io.IOException;
/**
* Observes, modifies, and potentially short-circuits requests going out and the corresponding
* responses coming back in. Typically interceptors add, remove, or transform headers on the request
* or response.
*/
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
interface Chain {
Request request();
Response proceed(Request request) throws IOException;
Connection connection();
}
}
代码不多,但感觉接口的使用方式,可以学习
拦截器作用:
Interceptors are a powerful mechanism that can monitor, rewrite, and retry
calls. Here's a simple interceptor that logs the outgoing request and the
incoming response
拦截器是一个强大的机制,可以监控,修改,重试 Call请求
个人理解:可以看作是海关,高速收费站
,对进出的船或车,进行把控
贴个图,不为别的,就是感觉这个图:简洁,优雅,大方,逼格
拦截有两种:Application Interceptor
和Network Interceptor
一个灰色矩形块块就是一个Interceptor
,一个OkHttpClient
可以添加多个Interceptor
拦截器
Application Interceptor
:主要多用于查看请求信息或者返回信息,如链接地址,头信息,参数等Network Interceptor
:多用于对请求体Request
或者响应体Response
的改变,缓存处理用这个
暂时也就知道这么多了,Interceptor.Chain
中3个方法具体做了啥,到了后面学习OkHttp
工程流程,再学习了解
2.1 Application Interceptor 简单使用
代码:直接加在OkHttpClient
中的addNetworkInterceptor
前就可以
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
String info_1 = String.format("Sending request %s on %s%n%s", request.url(),
chain.connection(), request.headers());
Log.e("info1", "-->" + info_1);
Response response = chain.proceed(request);
long t2 = System.nanoTime();
String info_2 = String.format("Received response for %s in %.1fms%n%s".toLowerCase(),
response.request().url(), (t2 - t1) / 1e6d, response.headers());
Log.e("info2", "-->" + info_2);
return response;
}
})
输出Log信息:
3. 最后
有错误,请指出
共勉 :)