OkHttp学习(七) 手写OkHttp之框架搭建

系列文章

OkHttp学习(一) OSI七层模型和TCP四层模型
OkHttp学习(二) 3.10.0版本的简单使用及其流程梳理
OkHttp学习(三) 3.10.0版本源码阅读之线程池
OkHttp学习(四) 3.10.0版本源码阅读之构建者设计模式
OkHttp学习(五) 3.10.0版本源码阅读之责任链设计模式
OkHttp学习(六) 3.10.0版本源码中的拦截器
OkHttp学习(七) 手写OkHttp之框架搭建
OkHttp学习(八) 手写OkHttp之网络请求实现
OkHttp学习(九) OkHttp的连接池手写实现

OkHttpClient2

public class OkHttpClient2 {

    Dispatcher2 dispatcher;

    boolean isCanceled;

    public boolean getCanceled() {
        return isCanceled;
    }

    public OkHttpClient2() {
        this(new Builder());
    }

    public OkHttpClient2(Builder builder) {
        dispatcher = builder.dispatcher;
        isCanceled = builder.isCanceled;
    }

    public final static class Builder {

        Dispatcher2 dispatcher;

        boolean isCanceled;

        public Builder() {
            dispatcher = new Dispatcher2();
        }

        public Builder dispatcher(Dispatcher2 dispatcher) {
            this.dispatcher = dispatcher;
            return this;
        }

        // 用户取消请求
        public Builder canceled() {
            isCanceled = true;
            return this;
        }

        public OkHttpClient2 build() {
            return new OkHttpClient2(this);
        }

    }

    public Call2 newCall(Request2 request2) {
        // RealCall
        return new RealCall2(this, request2);
    }

    public Dispatcher2 dispatcher() {
        return dispatcher;
    }

}

Request2

public class Request2 {
    public static final String GET = "GET";
    public static final String POST = "POST";

    private String url;
    private String requestMethod = GET; // 默认请求下是GET
    private Map<String, String> mHeaderList = new HashMap<>();

    public String getUrl() {
        return url;
    }

    public String getRequestMethod() {
        return requestMethod;
    }

    public Map<String, String> getmHeaderList() {
        return mHeaderList;
    }

    public Request2() {
        this(new Builder());
    }

    public Request2(Builder builder) {
        this.url = builder.url;
    }

    public final static class Builder {

        private String url;
        private String requestMethod = GET; // 默认请求下是GET
        private Map<String, String> mHeaderList = new HashMap<>();

        public Builder url(String url) {
            this.url = url;
            return this;
        }

        public Builder get() {
            requestMethod = GET;
            return this;
        }

        public Builder post() {
            requestMethod = POST;
            return this;
        }

        /**
         * Connection: keep-alive
         * Host: restapi.amap.com
         * @return
         */
        public Builder addRequestHeader(String key, String value) {
            mHeaderList.put(key, value);
            return this;
        }

        public Request2 build() {
            return new Request2(this);
        }

    }

}

Call2


public interface Call2 {

    void enqueue(Callback2 responseCallback);

}

RealCall2

public class RealCall2 implements Call2 {

    private OkHttpClient2 okHttpClient2;
    private Request2 request2;

    public RealCall2(OkHttpClient2 okHttpClient2, Request2 request2) {
        this.okHttpClient2 = okHttpClient2;
        this.request2 = request2;
    }

    private boolean executed;

    @Override
    public void enqueue(Callback2 responseCallback) {
        // 不能被重复的执行 enqueue
        synchronized (this) {
            if (executed) {
                executed = true;
                throw new IllegalStateException("不能被重复的执行 enqueue Already Executed");
            }
        }

        okHttpClient2.dispatcher().enqueue(new AsyncCall2(responseCallback));
    }

    final class AsyncCall2 implements Runnable {

        public Request2 getRequest() {
            return RealCall2.this.request2;
        }

        private Callback2 callback2;

        public AsyncCall2(Callback2 callback2) {
            this.callback2 = callback2;
        }

        @Override
        public void run() {
            // 执行耗时操作
            boolean signalledCallback = false;
            try {
                Response2 response = getResponseWithInterceptorChain();
                // 如果用户取消了请求,回调给用户,说失败了
                if (okHttpClient2.getCanceled()) {
                    signalledCallback = true;
                    callback2.onFailure(RealCall2.this, new IOException("用户取消了 Canceled"));
                } else {
                    signalledCallback = true;
                    callback2.onResponse(RealCall2.this, response);
                }

            }catch (IOException e) {
                // 责任的划分
                if (signalledCallback) { // 如果等于true,回调给用户了,是用户操作的时候 报错
                    System.out.println("用户再使用过程中 出错了...");
                } else {
                    callback2.onFailure(RealCall2.this, new IOException("OKHTTP getResponseWithInterceptorChain 错误... e:" + e.toString()));
                }
            } finally {
                // 回收处理
                okHttpClient2.dispatcher().finished(this);
            }
        }

        private Response2 getResponseWithInterceptorChain() throws IOException {
            Response2 response2 = new Response2();
            response2.setBody("流程走通....");
            return response2;
        }
    }
}

Dispatcher2

public class Dispatcher2 {

    private int maxRequests = 64; // 同时访问任务,最大限制64个
    private int maxRequestsPerHost = 5; // 同时访问同一个服务器域名,最大限制5个

    private Deque<RealCall2.AsyncCall2> runningAsyncCalls = new ArrayDeque<>(); // 存储运行的队列
    private Deque<RealCall2.AsyncCall2> readyAsyncCalls = new ArrayDeque<>(); // 存储等待的队列

    public void enqueue(RealCall2.AsyncCall2 call) {
        // 同时运行的队列数 必须小于 配置的64   && 同时访问同一个服务器域名 不能超过5个
        if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
            runningAsyncCalls.add(call); // 先把任务加入到 运行队列中
            executorService().execute(call); // 然后再执行....
        } else {
            readyAsyncCalls.add(call); // 加入到等待队列中
        }
    }

    /**
     * 缓存方案
     * @return
     */
    public ExecutorService executorService() {
        ExecutorService executorService =
                new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                        60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
                        new ThreadFactory() {
                            @Override
                            public Thread newThread(Runnable r) {
                                Thread thread = new Thread(r);
                                thread.setName("自定义的线程....");
                                thread.setDaemon(false); // 不是守护线程
                                return thread;
                            }
                        });
        return executorService;
    }

    /**
     * 判断AsyncCall2中的Host,在运行的队列中,计数,然后放回
     *
     * 参数AsyncCall2.Request.Host  == runningAsyncCalls.for{AsyncCall2.Request.Host} +1
     *
     * @param call
     * @return
     */
    private int runningCallsForHost(RealCall2.AsyncCall2 call) {
        int count = 0;
        if (runningAsyncCalls.isEmpty()) {
            return 0;
        }

        SocketRequestServer srs = new SocketRequestServer();

        /**
         * 遍历运行队列里面的所有任务,取出任务host == call.host +1
         */
        for (RealCall2.AsyncCall2 runningAsyncCall : runningAsyncCalls) {
            // 取出任务host == call.host
            if (srs.getHost(runningAsyncCall.getRequest()).equals(call.getRequest())) {
                count ++;
            }
        }

        return count;
    }

    /**
     * 1.移除运行完成的任务
     * 2.把等待队列里面所有的任务取出来【执行】  AsyncCall2.run finished
     * @param call2
     */
    public void finished(RealCall2.AsyncCall2 call2) {
        // 当前运行的任务 给回收
        runningAsyncCalls.remove(call2);

        // 考虑等待队列里面是否有任务,如果有任务是需要执行的
        if (readyAsyncCalls.isEmpty()) {
            return;
        }

        // 把等待队列中的任务给 移动 运行队列
        for (RealCall2.AsyncCall2 readyAsyncCall : readyAsyncCalls) {
            readyAsyncCalls.remove(readyAsyncCall); // 删除等待队列的任务

            runningAsyncCalls.add(readyAsyncCall); // 把刚刚删除的等待队列任务 加入到 运行队列

            // 开始执行任务
            executorService().execute(readyAsyncCall);
        }
    }
}

Callback2


public interface Callback2 {

    void onFailure(Call2 call, IOException e);

    void onResponse(Call2 call, Response2 response) throws IOException;
}

Response2

public class Response2 {

    private String body;

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String string() {
        return body;
    }

}

SocketRequestServer

public class SocketRequestServer {

    /**
     * 通过Request对象,寻找到域名HOST
     * @param request2
     * @return
     */
    public String getHost(Request2 request2) {
        return null;
    }

}

测试代码

/**
* 使用我们自己的OKHTTP
* @param view
*/
public void useMyOkhttp(View view) {
OkHttpClient2 okHttpClient2 = new OkHttpClient2.Builder().build();

    Request2 request2 = new Request2.Builder().url(PATH).build();

    Call2 call2 = okHttpClient2.newCall(request2);

    // 执行异步
    call2.enqueue(new Callback2() {
        @Override
        public void onFailure(Call2 call, IOException e) {
            System.out.println("自定义OKHTTP请求失败....");
        }

        @Override
        public void onResponse(Call2 call, Response2 response) throws IOException {
            System.out.println("OKHTTP请求成功.... result:" + response.string());
        }
    });
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值