# 特色

# 使用 HttpUtils 类

HttpUtils本是 前身 HttpUtils 的 1.x 版本里的最重要的核心类,由于在后来的版本里抽象出了HTTP接口,使得它的重要性已不如往昔。但合理的使用它,仍然可以带来不少便利,特别是在没有IOC容器的环境里,比如在Android开发和一些工具项目的开发中。

HttpUtils共定义了四个静态方法:

  • of(HTTP http) 配置HttpUtils持有的HTTP实例(不调用此方法前默认使用一个没有没有经过任何配置的HTTP懒实例)
  • sync(String url) 开始一个同步请求 (内部通过一个HTTP单例实现)
  • async(String url) 开始一个异步请求 (内部通过一个HTTP单例实现)
  • cancel(String tag) 按标签取消请求(内部通过一个HTTP单例实现)
  • cancelAll() 取消所有HTTP任务,包括同步和异步(内部通过一个HTTP单例实现)
  • request(Request request) OkHttp 原生请求 (该请求不经过 预处理器)
  • webSocket(Request request, WebSocketListener listener) WebSocket通讯   也就是说,能使用http实例的地方,都可以使用HttpUtils类,例如:
// 在配置HTTP实例之前,只能使用全路径方式
List<Role> roles = HttpUtils.sync("http://api.demo.com/roles")
        .get().getBody().toList(Role.class);

// 配置HTTP实例,全局生效
HttpUtils.of(HTTP.builder()
        .baseUrl("http://api.demo.com")
        .build());

// 内部使用新的HTTP实例
List<User> users = HttpUtils.sync("/users")
        .get().getBody().toList(User.class);
1
2
3
4
5
6
7
8
9
10
11
12

# 异常处理

使用 OkHttps 时,异常处理不是必须的,但相比其它的 HTTP 开发包,它还提供一个特别的处理方法:nothrow(),以满足不同的异常处理需求。

# 同步请求的异常

默认情况下,当同步请求执行异常时,会直接向外抛出,我们可以用 try catch 来捕获,例如:

try {
    HttpResult result = http.sync("/users/1").get();
} catch (HttpException e) {
    Throwable cause = e.getCause(); // 得到异常原因
    if (cause instanceof ConnectException) {
        // 当没网络时,会抛出连接异常
    }
    if (cause instanceof SocketTimeoutException) {
        // 当接口长时间未响应,会抛出超时异常
    }
    if (cause instanceof UnknownHostException) {
        // 当把域名或IP写错,会抛出 UnknownHost 异常
    }
    // ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

这种传统的异常处理方式,当然可以解决问题,但 OkHttps 有更佳的方案:

// 方法  nothrow() 让异常不直接抛出
HttpResult result = http.sync("/users/1").nothrow().get();
// 判断执行状态
switch (result.getState()) {
    case RESPONSED:     // 请求已正常响应
        break;
    case CANCELED:      // 请求已被取消
        break;
    case NETWORK_ERROR: // 网络错误,说明用户没网了
        break;
    case TIMEOUT:       // 请求超时
        break;
    case EXCEPTION:     // 其它异常
        break;
}
// 还可以获得具体的异常信息
IOException error = result.getError();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 异步请求的异常

异步请求最常用的异常处理方式就是设置一个异常回调:

http.async("/users/1")
        .setOnResponse((HttpResult result) -> {
            // 当发生异常时就不会走这里
        })
        .setOnException((IOException e) -> {
            // 这里处理请求异常
        })
        .get();
1
2
3
4
5
6
7
8

当然,还有一个全局异常监听(ExceptionListener):

HTTP http = HTTP.builder()
        .exceptionListener((HttpTask<?> task, IOException error) -> {
            // 所有请求发生异常都会走这里

            return true; // 返回 true 表示继续执行 task 的 OnException 回调,false 表示不再执行
        })
        .build();
1
2
3
4
5
6
7

如果不设置OnException回调,也没有ExceptionListener,发生异常时会在 IO 线程 中向上抛出,外层无法捕获:

try {
    http.async("/users/1")
            .setOnResponse((HttpResult result) -> {
                // 当发生异常时就不会走这里
            })
            .get();
} catch (HttpException e) {
    // 这种方式是捕获不到异常的!!!!!!
}
1
2
3
4
5
6
7
8
9

即使没有OnException回调,发生异常时,依然会走OnComplete回调,如果设置了的话:

http.async("/users/1")
        .setOnResponse((HttpResult result) -> {
            // 当发生异常时就不会走这里
        })
        .setOnComplete((State state) -> {
            // 发生异常,会先执行这里,可以根据 state 判断发生了什么
            // 但执行完后依然会在IO线程中向上抛出
        })
        .get();
1
2
3
4
5
6
7
8
9

如果就是想 不处理异常,也不向上抛出,发生错误完全无视,可以做到吗?可以!还是使用nothrow()方法:

http.async("/users/1")
        .nothrow()  // 告诉 OkHttps 发生异常时不向外抛出
        .setOnResponse((HttpResult result) -> {
            // 当发生异常时就不会走这里
        })
        .get();
1
2
3
4
5
6

# 取消请求

在 OkHttps 里取消请求共有 4 种 方式可选:

  • 使用HttpCall#cancel()取消单个请求(适用于异步请求,详见 3.3 章节
  • 使用HttpTask#cancel()取消单个请求(适用于所有请求)(since v1.0.4)
HttpTask<?> task = http.async("/users")
        .setOnResponse((HttpResult result) -> {
            // 响应回调
        });

task.get(); // 发起 GET 请求

// 取消请求,并返回是否取消成功
boolean canceled = task.cancel();   
1
2
3
4
5
6
7
8
9
  • 使用HTTP#cancel(String tag)按标签批量取消请求(适用于所有请求,详见第 5 章节
  • 使用HTTP#cancelAll()取消所有请求(适用于所有请求)(since v1.0.2)
http.cancelAll();   // 取消所有请求
1