android http重复请求,okhttp处理短时间内的重复请求

关键点

判断请求是否相同: request转key,根据key判断

请求进行中: 等待

请求已完成: 返回缓存的response

过去这段时间后,清除缓存的response

代码实现:

public class SameRequestFilterInterceptor implements Interceptor {

static WeakHashMap responseWeakHashMap = new WeakHashMap<>();

static WeakHashMap> calls = new WeakHashMap<>();

static Charset UTF_8 = Charset.forName("UTF-8");

static IConfig config;

static boolean enableFilter;

static boolean debug;

static Handler handler;

/**

* @param enableFilter 全局开关

* @param config 配置信息

*/

public static void config(boolean debug, boolean enableFilter, IConfig config) {

SameRequestFilterInterceptor.enableFilter = enableFilter;

SameRequestFilterInterceptor.config = config;

SameRequestFilterInterceptor.debug = debug;

}

@Override

public Response intercept(Chain chain) throws IOException {

Request request = chain.request();

if (!enableFilter) {

return chain.proceed(request);

}

if (config == null) {

return chain.proceed(request);

}

if (!config.shouldFilter(request.url().toString())) {

return chain.proceed(request);

}

String key = generateKey(request);

return check(chain, request, key);

}

private Response check(Chain chain, Request request, String key) throws IOException {

try {

//从缓存的call和response中判断要不要等待

boolean needwait = needwait(key);

if (!needwait) {

if (responseWeakHashMap.containsKey(key)) {

return responseWeakHashMap.get(key).getClonedResonse();

} else {

//直接执行请求:

//将response缓存起来

return realExceute(chain, request, key);

}

} else {

Thread.sleep(2000);

return check(chain, request, key);

}

} catch (InterruptedException e) {

e.printStackTrace();

if (responseWeakHashMap.containsKey(key)) {

return responseWeakHashMap.get(key).getClonedResonse();

} else {

//直接执行请求:

//将response缓存起来

return realExceute(chain, request, key);

}

}

}

@NonNull

private Response realExceute(Chain chain, Request request, String key) throws IOException {

calls.put(key, new WeakReference<>(chain.call()));

Response response = chain.proceed(request);

if (response.isSuccessful() && response.body() != null) {

ResponseBody responseBody = response.body();

BufferedSource source = responseBody.source();

source.request(responseBody.contentLength() > 0 ? responseBody.contentLength() : Integer.MAX_VALUE);

//吓人?

Buffer buffer = source.buffer();

Charset charset = UTF_8;

MediaType contentType = responseBody.contentType();

if (contentType != null) {

charset = contentType.charset(UTF_8);

}

String bodyString = buffer.clone().readString(charset);

ResponseBody cloneBody = ResponseBody.create(response.body().contentType(), bodyString);

Response responseClone = new Response.Builder()

.code(response.code())

.protocol(response.protocol())

.message(response.message())

.body(cloneBody)

.headers(response.headers())

.header("cachedResonse", "yes")

.request(request)

.build();

responseWeakHashMap.put(key, new ResonseForClone(bodyString, responseClone));

calls.remove(key);

getMainHandler().postDelayed(new Runnable() {

@Override

public void run() {

//1min后移除缓存的response:

responseWeakHashMap.remove(key);

logw(config.responseCacheTimeInMills() + "时间到了,清除缓存的response");

}

}, config.responseCacheTimeInMills());

}

return response;

}

private static Handler getMainHandler() {

if (handler == null) {

handler = new Handler(Looper.getMainLooper());

}

return handler;

}

private boolean needwait(String key) {

if (responseWeakHashMap.containsKey(key)) {

logw("有缓存的response,直接去读缓存,并组装新的response");

return false;

}

if (calls.containsKey(key)) {

WeakReference callWeakReference = calls.get(key);

if (callWeakReference == null) {

logw("不需要等待,直接发请求 call WeakReference not exist:");

return false;

}

Call call = callWeakReference.get();

if (call == null || call.isCanceled()) {

logw("不需要等待,直接发请求 call not exist or is canceld:" + call);

return false;

}

logw("请求可能正在等待或正在执行-needwait call is running:" + call);

//请求可能正在等待或正在执行

return true;

}

logw("任何地方都没有,不需要等,直接执行请求");

//任何地方都没有,不需要等,直接执行请求

return false;

}

private static void logw(String str) {

if (debug) {

Log.w("requestFilter", str);

}

}

/**

* @param request

* @return

*/

private String generateKey(Request request) {

return config.generateCacheKey(request);

}

class ResonseForClone {

String body;

Response response;

public ResonseForClone(String body, Response response) {

this.body = body;

this.response = response;

}

public Response getClonedResonse() {

ResponseBody cloneBody = ResponseBody.create(response.body().contentType(), body);

Response responseClone = new Response.Builder()

.code(response.code())

.protocol(response.protocol())

.message(response.message())

.body(cloneBody)

.headers(response.headers())

.header("cachedResonse", "yes")

.request(response.request())

.build();

return responseClone;

}

}

public interface IConfig {

boolean shouldFilter(String url);

String generateCacheKey(Request request);

long responseCacheTimeInMills();

}

}

使用:

SameRequestFilterInterceptor.config(Config.enableLog(), true, new SameRequestFilterInterceptor.IConfig() {

@Override

public boolean shouldFilter(String url) {

return true;

}

@Override

public String generateCacheKey(Request request) {

return request.url().toString();

}

@Override

public long responseCacheTimeInMills() {

return 60000;

}

});

commonInterceptors.add(new SameRequestFilterInterceptor());

demo:

for (int i = 0; i < 20; i++) {

request();

}

日志:

39ea6c46cc22

image.png

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
关于框架有意见 欢迎联系我一起探讨。 问答是happy http://blog.csdn.net/b275518834/article/details/8247685 操作方式:输入文本框设置线程数 点击第一个按钮请求10个地址信息 点击第二个按钮中断10个地址信息 1:判断当前网络环境 2:编写了3套方案 Old_GridViewActivity 简单线程回调 AsyncTask_GridViewActivity 使用android自带的AsyncTask类实现 Demo_GridViewActivity 队列任务管理 线程控制 Demo_GridViewActivity方式 1:队列优先级 (如果想要listview中移动的区域优先被显示,而不是从上到下显示图片,可以把新建的任务提到任务队列前端) 2:实现了:中断任务的功能(比如进入一个Activity会开启大量任务,如果退出这个Activity 则应该停止此Activity中驻留的任务) 3:为何采用drawable不用bitmap bitmap优点是位图运算效率优秀 但drawable的存储体积比bitmap小 4:如果任务被起名字则禁止重复提交任务 (避免某些请求处理完又被创建) 5:先执行缓存数据后执行请求数据 (缓存性能) 6:使用状态模式 观察者模式更好的处理多线程 最初的想法:网络优化开发框架 (移除任务未完成) 网络稳定,系统运行稳定性,大内存消耗稳定,长时间运行稳定性 (旧的系统症结所在) 开启过多线程,导致系统频繁切换多个线程,导致处理速度过慢,经常出现未响应。 代码经常写的换繁多无序,维护困难。 使用类似银行叫号系统 线程池内等待网络请求的任务=(排队的人) 最大三个线程=(银行柜台处理业务的窗口) 依次处理任务=(将排队的人依次被叫到处理的号,完成业务的窗口叫号后面排队的人) 如果抛出异常则通知相关单位=(如果银行柜台处理不了一个人的业务就打电话给大堂经理) 设置柜台的监听回调=(A委托B去银行请求数据,当B去银行处理业务失败了,通知A。) 设置撤销机制和线程安全= 某机关让A和B去银行申请业务,A在排队,B正在柜台处理业务,此时机关打来电话说, 这申请业务的需求现在不做,A取消排队,B也‘礼貌的退出’ 《例如退出A页面时,终止A页面所有的请求》 任务状态标示-还没处理 处理处理结束 处理异常 (有结果但不通知)=(排队人的状态) 任务名 排队人的名字 强制退出 强制退出 抛出强制退出的异常

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值