当前位置: 代码迷 >> 综合 >> OKHTTP 源码分析(3)责任链模式
  详细解决方案

OKHTTP 源码分析(3)责任链模式

热度:31   发布时间:2023-11-17 10:33:00.0

序 、最近几天心情不太美丽 。

 

源码

调用 OKHTTP 最后返回 Response ,当然要看责任链模式 。无论是异步还是同步 ,都需要通过责任链调用得到 Response 。

RealCall 类 :Response getResponseWithInterceptorChain() throws IOException {// Build a full stack of interceptors.List<Interceptor> interceptors = new ArrayList<>();interceptors.addAll(client.interceptors()); //首先添加的是用户添加的全局拦截器interceptors.add(retryAndFollowUpInterceptor);//错误、重定向拦截器//桥接拦截器,桥接应用层与网络层,添加必要的头interceptors.add(new BridgeInterceptor(client.cookieJar()));//缓存处理,Last-Modified、ETag、DiskLruCacheinterceptors.add(new CacheInterceptor(client.internalCache()));//连接拦截器interceptors.add(new ConnectInterceptor(client));//从这就知道,通过okHttpClient.Builder#addNetworkInterceptor()传进来的拦截器只对非网页的请求生效if (!forWebSocket) {interceptors.addAll(client.networkInterceptors());}//真正访问服务器的拦截器interceptors.add(new CallServerInterceptor(forWebSocket));Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,originalRequest, this, eventListener, client.connectTimeoutMillis(),client.readTimeoutMillis(), client.writeTimeoutMillis());return chain.proceed(originalRequest);}

PS:一共可以看到六个拦截器 。顺序是重定向拦截器 、桥拦截器 、缓存拦截器 、连接拦截器 、网络拦截器 、访问服务拦截器 。为什么我会这样写呢 ?不瞒你说 ,曾经有个面试官问过我这个问题(请说一下OKHTTP中有几个拦截器 ,并且说明拦截器的顺序) 。哈哈哈哈 、、、

 

责任链模式

顾名思义是为请求创建了一个接受者对象的链 。这种模式给予请求的类型 ,对请求的发送者和接受者进行解耦 。在这种模式中通常每个接受者都会包含对另一个接受者的引用 ,如果一个对象不能处理该请求 ,那么他会把相同的请求传递给下一个接收者 ,以此类推 。(有没有想起来 View 的事件分发)

特点

责任链模式可以使请求能被多个对象依次进行处理 ,从而使这些形象形成一条完成的链路 。这样就会使请求由起始点 ,顺着这条链路 ,依次向下一个对象进行传递 ,直至传递到最后一个对象 。

场景

1.当一个请求可能会被某个环节修改 ,并且该环节修改请求后 ,会将该请求继续下发给下一个环节 。

2.请求处理环节可能会发生改变 ,有可能改变其中某个环节 ,也有可能所有的流程发生更新 。比如网络请求 ,将网络请求环节中的重定向 、重试 、拦截器以模块的形式进行责任链连接 。

直接上示例代码 基础写法

1.责任链父类

public abstract class BaseChain {//判断当前任务节点 有没有能力执行private boolean isDoChain = false;public BaseChain(boolean isDoChain) {super();this.isDoChain = isDoChain;}// 执行下一个节点private BaseChain nextChain;// 添加下一个节点任务public void addNextChain(BaseChain nextChain) {this.nextChain = nextChain;}// 子任务节点 执行public abstract void doAction();public void action() {if (isDoChain) {doAction(); // 执行} else {if(nextChain != null)nextChain.action(); //继续执行下一个任务}}}

2.子节点 Chain1 、Chain2 、Chain3 

public class Chain1 extends BaseChain{public Chain1(boolean isDoChain) {super(isDoChain);}@Overridepublic void doAction() {//执行子节点Log.i("Chain","这是 Chain 1 ,老哥");}
}

3. 调用 

   private void initChain() {Chain1 chain1 = new Chain1(false);Chain2 chain2 = new Chain2(false);Chain3 chain3 = new Chain3(true);Chain4 chain4 = new Chain4(false);chain1.addNextChain(chain2);chain2.addNextChain(chain3);chain3.addNextChain(chain4);chain1.action();}

打印结果

2020-07-28 16:48:39.459 3539-3539/com.developers.myapplication I/Chain: 这是 Chain 3 ,老哥

跟 OKHTTP 类似的写法

1.接口

public interface IBaseTask {/**** @param isTask 任务节点是否有能力执行* @@param iBaseTask 下一个任务节点*/public void doRunAction(String isTask, IBaseTask iBaseTask);}

2.责任链管理类

public class ChainManager implements IBaseTask {private List<IBaseTask> iBaseTaskList = new ArrayList<>();//添加子节点public void addTask(IBaseTask iBaseTask) {iBaseTaskList.add(iBaseTask);}//索引private int index = 0;//执行@Overridepublic void doRunAction(String isTask, IBaseTask iBaseTask) {if (iBaseTaskList.isEmpty()) return; //抛异常if (index == iBaseTaskList.size() || index > iBaseTaskList.size()) {return;}IBaseTask iBaseTaskResult = iBaseTaskList.get(index);// t1index ++;iBaseTaskResult.doRunAction(isTask,iBaseTask);}
}

3.子节点 Chain1 、Chain2 、Chain3 

public class Chain_1 implements IBaseTask {@Overridepublic void doRunAction(String isTask, IBaseTask iBaseTask) {if ("ok1".equals(isTask)) {Log.i("Chain", "任务节点一 ,处理了 。老哥");return;} else {iBaseTask.doRunAction(isTask, iBaseTask);}}
}

4.调用

  private void initChain2() {ChainManager chainManager =new ChainManager();chainManager.addTask(new Chain_1());chainManager.addTask(new Chain_2());chainManager.addTask(new Chain_3());chainManager.addTask(new Chain_4());chainManager.doRunAction("ok",chainManager);}

上述代码示例跟 OKHTTP 的责任链实现思路是一致的,可以说是简化版的 OKHTTP 的责任链 。

 

本来想在分析一下 OKHTTP 的责任链源码 。

大概能看到 index +1 ,做自循环操作 。

 

 

。。。
Wait

。。。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  相关解决方案