Skip to content

Commit b2b10da

Browse files
committed
优化网络请求日志的 TAG 名称
优化反射性能(利用 LruCache 缓存) 新增支持设置回调监听所在的线程类型 新增 IRequestHandler 下载失败处理逻辑 新增 Delete 使用 Body 传参的请求方法 修复请求 Bean 类为流类型时流被关闭的问题 修正上传文件时带中文的文件名被编码的问题
1 parent 4a0c7a9 commit b2b10da

25 files changed

+468
-203
lines changed

.github/ISSUE_TEMPLATE/issue_template_bug.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,31 @@ assignees: getActivity
88

99
## 问题描述
1010

11-
* 框架版本:XXX
11+
* 框架版本【必填】:XXX
1212

13-
* 问题描述:XXX
13+
* 问题描述【必填】:XXX
1414

15-
* 复现步骤:XXX
15+
* 复现步骤【必填】:XXX
1616

17-
* 是否必现:填是/否
17+
* 是否必现【必填】:填是/否
1818

19-
* 出现问题的手机信息:请填写出现问题的品牌和机型
19+
* 出现问题的手机信息【必填】:请填写出现问题的品牌和机型
2020

21-
* 出现问题的安卓版本:请填写出现问题的 Android 版本
21+
* 出现问题的安卓版本【必填】:请填写出现问题的 Android 版本
2222

2323
## 请回答
2424

25-
* 是部分机型还是所有机型都会出现:部分/全部(例如:某为,某 Android 版本会出现)
25+
* 是部分机型还是所有机型都会出现【必答】:部分/全部(例如:某为,某 Android 版本会出现)
2626

27-
* 框架最新的版本是否存在这个问题:是/否(如果用的是旧版本的话,建议升级看问题是否还存在)
27+
* 框架最新的版本是否存在这个问题【必答】:是/否(如果用的是旧版本的话,建议升级看问题是否还存在)
2828

29-
* 是否已经查阅框架文档还未能解决的:是/否(文档会提供最常见的问题解答,可以看看是否有自己想要的)
29+
* 是否已经查阅框架文档还未能解决的【必答】:是/否(文档会提供最常见的问题解答,可以看看是否有自己想要的)
3030

31-
* issue 是否有人曾提过类似的问题:是/否(看看曾经有人提过类似的问题,先参考一下别人是怎么解决的)
31+
* issue 是否有人曾提过类似的问题【必答】:是/否(看看曾经有人提过类似的问题,先参考一下别人是怎么解决的)
3232

33-
* 是否可以通过 Demo 来复现该问题:是/否(排查一下是不是自己的项目代码写得有问题导致的)
33+
* 是否可以通过 Demo 来复现该问题【必答】:是/否(排查一下是不是自己的项目代码写得有问题导致的)
3434

35-
* 这个问题是不是后台自己的问题导致的:是/否(如果无法确定问题的原因,请先和后台开发人员协商联调,确认了问题是框架的再反馈给作者,如果是后台的问题作者也没用,最后还是要自己找后台处理才有用的)
35+
* 这个问题是不是后台自己的问题导致的【必答】:是/否(如果无法确定问题的原因,请先和后台开发人员协商联调,确认了问题是框架的再反馈给作者,如果是后台的问题作者也没用,最后还是要自己找后台处理才有用的)
3636

3737
## 其他
3838

.github/ISSUE_TEMPLATE/issue_template_suggest.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ assignees: getActivity
88

99
## 建议收集
1010

11-
* issue 是否有人曾提过类似的问题?(必答项,一旦出现重复提问我将不会再次解答)
11+
* issue 是否有人曾提过类似的问题?【必答】(一旦出现重复提问我将不会再次解答)
1212

13-
* 你觉得框架有什么不足之处?(必答项,你可以描述框架有什么令你不满意的地方)
13+
* 你觉得框架有什么不足之处?【必答】(你可以描述框架有什么令你不满意的地方)
1414

15-
* 你觉得该怎么去完善会比较好?(非必答项,你可以提供一下自己的想法或者做法供作者参考)
15+
* 你觉得该怎么去完善会比较好?【非必答】(你可以提供一下自己的想法或者做法供作者参考)

HelpDoc.md

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272

7373
* [如何对接口路径进行动态化拼接](#如何对接口路径进行动态化拼接)
7474

75+
* [如何动态化整个请求的 url](#如何动态化整个请求的-url)
76+
7577
* [Https 如何配置信任所有证书](#https-如何配置信任所有证书)
7678

7779
* [我不想一个接口写一个类怎么办](#我不想一个接口写一个类怎么办)
@@ -88,6 +90,8 @@
8890

8991
* [如何设置自定义的 UA 标识](#如何设置自定义的-ua-标识)
9092

93+
* [我想修改请求回调所在的线程该怎么办](#我想修改请求回调所在的线程该怎么办)
94+
9195
* [我想自定义一个 RequestBody 进行请求该怎么办](#我想自定义一个-requestbody-进行请求该怎么办)
9296

9397
* [搭配 RxJava](#搭配-rxjava)
@@ -281,7 +285,7 @@ public final class XxxApi implements IRequestServer, IRequestApi {
281285

282286
#### 发起请求
283287

284-
* 需要配置请求状态及生命周期处理,具体封装可以参考 [BaseActivity](app/src/main/java/com/hjq/http/demo/BaseActivity.java)
288+
* 需要配置请求状态及生命周期处理,具体封装可以参考 [BaseActivity](app/src/main/java/com/hjq/easy/demo/BaseActivity.java)
285289

286290
```java
287291
EasyHttp.post(this)
@@ -1170,6 +1174,20 @@ public final class XxxApi implements IRequestApi {
11701174
}
11711175
```
11721176

1177+
#### 如何动态化整个请求的 url
1178+
1179+
```java
1180+
EasyHttp.post(this)
1181+
.api(new RequestUrl("https://xxxx.com/aaaa"))
1182+
.request(new HttpCallback<Xxx>(this) {
1183+
1184+
@Override
1185+
public void onSucceed(Xxx result) {
1186+
1187+
}
1188+
});
1189+
```
1190+
11731191
#### Https 如何配置信任所有证书
11741192

11751193
* 在初始化 OkHttp 的时候这样设置
@@ -1240,7 +1258,7 @@ EasyHttp.post(new ActivityLifecycle(this))
12401258
* 如果以上条件都不满足,但是你就是想在某个地方请求网络,那么你可以这样写
12411259

12421260
```java
1243-
EasyHttp.post(new ApplicationLifecycle())
1261+
EasyHttp.post(ApplicationLifecycle.getInstance())
12441262
.api(new XxxApi())
12451263
.tag("abc")
12461264
.request(new OnHttpListener<HttpData<XxxBean>>() {
@@ -1422,6 +1440,22 @@ EasyHttp.post(this)
14221440

14231441
* 首先 UA 是 User Agent 的简称,当我们没有设置自定义 UA 标识的时候,那么 OkHttp 会在 BridgeInterceptor 拦截器添加一个默认的 UA 标识,那么如何在 EasyHttp 设置自定义 UA 标识呢?其实很简单,UA 标识本质上其实就是一个请求头,在 EasyHttp 中添加一个请求头为 `"User-Agent` 的参数即可,至于怎么添加请求头,前面的文档已经有介绍了,这里不再赘述。
14241442

1443+
#### 我想修改请求回调所在的线程该怎么办
1444+
1445+
```
1446+
EasyHttp.post(this)
1447+
.api(new XxxApi())
1448+
// 表示回调是在子线程中进行
1449+
.schedulers(ThreadSchedulers.IOThread)
1450+
.request(new HttpCallback<HttpData<Xxx>>(this) {
1451+
1452+
@Override
1453+
public void onSucceed(HttpData<Xxx> result) {
1454+
1455+
}
1456+
});
1457+
```
1458+
14251459
#### 我想自定义一个 RequestBody 进行请求该怎么办
14261460

14271461
* 在一些极端的情况下,框架无法满足使用的前提下,这个时候需要自定义 `RequestBody` 来实现,那么怎么使用自定义 `RequestBody` 呢?框架其实有开放方法,具体使用示例如下:

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
* 博客地址:[网络请求,如斯优雅](https://www.jianshu.com/p/93cd59dec002)
66

7-
* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处下载Demo](https://github.com/getActivity/EasyHttp/releases/download/11.0/EasyHttp.apk)
7+
* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处下载Demo](https://github.com/getActivity/EasyHttp/releases/download/11.2/EasyHttp.apk)
88

99
![](picture/demo_code.png)
1010

@@ -61,7 +61,7 @@ android {
6161
6262
dependencies {
6363
// 网络请求框架:https://github.com/getActivity/EasyHttp
64-
implementation 'com.github.getActivity:EasyHttp:11.0'
64+
implementation 'com.github.getActivity:EasyHttp:11.2'
6565
// OkHttp 框架:https://github.com/square/okhttp
6666
// noinspection GradleDependency
6767
implementation 'com.squareup.okhttp3:okhttp:3.12.13'
@@ -76,9 +76,9 @@ dependencies {
7676

7777
| 功能或细节 | [EasyHttp](https://github.com/getActivity/EasyHttp) | [Retrofit](https://github.com/square/retrofit) | [OkGo](https://github.com/jeasonlzy/okhttp-OkGo) |
7878
| :----: | :------: | :-----: | :-----: |
79-
| 对应版本 | 11.0 | 2.9.0 | 3.0.4 |
79+
| 对应版本 | 11.2 | 2.9.0 | 3.0.4 |
8080
| issues 数 | [![](https://img.shields.io/github/issues/getActivity/EasyHttp.svg)](https://github.com/getActivity/EasyHttp/issues) | [![](https://img.shields.io/github/issues/square/retrofit.svg)](https://github.com/square/retrofit/issues) | [![](https://img.shields.io/github/issues/jeasonlzy/okhttp-OkGo.svg)](https://github.com/jeasonlzy/okhttp-OkGo/issues) |
81-
| **aar 包大小** | 80 KB | 123 KB | 131 KB |
81+
| **aar 包大小** | 86 KB | 123 KB | 131 KB |
8282
| minSdk 要求 | API 14+ | API 21+ | API 14+ |
8383
| 配置多域名 ||||
8484
| **动态 Host** ||||

app/build.gradle

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ android {
1313
applicationId 'com.hjq.easy.demo'
1414
minSdkVersion 16
1515
targetSdkVersion 31
16-
versionCode 1100
17-
versionName '11.0'
16+
versionCode 1120
17+
versionName '11.2'
1818
}
1919

2020
// 支持 JDK 1.8
@@ -63,31 +63,33 @@ dependencies {
6363

6464
// AndroidX 库:https://github.com/androidx/androidx
6565
implementation 'androidx.appcompat:appcompat:1.4.0'
66+
// Material 库:https://github.com/material-components/material-components-android
67+
implementation 'com.google.android.material:material:1.4.0'
6668

6769
// OkHttp 框架:https://github.com/square/okhttp
6870
// 升级注意事项:https://www.jianshu.com/p/d12d0f536f55
6971
// noinspection GradleDependency
7072
implementation 'com.squareup.okhttp3:okhttp:3.12.13'
7173

7274
// 吐司框架:https://github.com/getActivity/ToastUtils
73-
implementation 'com.github.getActivity:ToastUtils:10.3'
75+
implementation 'com.github.getActivity:ToastUtils:10.5'
7476

7577
// 权限请求框架:https://github.com/getActivity/XXPermissions
76-
implementation 'com.github.getActivity:XXPermissions:13.5'
78+
implementation 'com.github.getActivity:XXPermissions:15.0'
7779

7880
// 标题栏框架:https://github.com/getActivity/TitleBar
79-
implementation 'com.github.getActivity:TitleBar:9.3'
81+
implementation 'com.github.getActivity:TitleBar:9.5'
8082

8183
// Json 解析框架:https://github.com/google/gson
8284
implementation 'com.google.code.gson:gson:2.9.0'
8385
// Gson 解析容错:https://github.com/getActivity/GsonFactory
84-
implementation 'com.github.getActivity:GsonFactory:6.0'
86+
implementation 'com.github.getActivity:GsonFactory:6.2'
8587

8688
// 腾讯 MMKV:https://github.com/Tencent/MMKV
8789
implementation 'com.tencent:mmkv-static:1.2.12'
8890

8991
// 日志调试框架:https://github.com/getActivity/Logcat
90-
debugImplementation 'com.github.getActivity:Logcat:10.3'
92+
debugImplementation 'com.github.getActivity:Logcat:10.6'
9193

9294
// 内存泄漏监测框架:https://github.com/square/leakcanary
9395
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1'

app/src/main/java/com/hjq/easy/demo/MainActivity.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.hjq.easy.demo.http.model.HttpData;
2525
import com.hjq.http.EasyHttp;
2626
import com.hjq.http.EasyUtils;
27+
import com.hjq.http.exception.FileMD5Exception;
2728
import com.hjq.http.listener.HttpCallback;
2829
import com.hjq.http.listener.OnDownloadListener;
2930
import com.hjq.http.listener.OnUpdateListener;
@@ -184,7 +185,7 @@ public void onSucceed(HttpData<SearchBlogsApi.Bean> result) {
184185
// }
185186

186187
// 如果是放到外部存储的应用专属目录则不需要适配分区存储特性
187-
File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "EasyHttp.png");
188+
File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "我是测试专用的图片.png");
188189

189190
if (!file.exists()) {
190191
// 生成图片到本地
@@ -286,7 +287,11 @@ public void onComplete(File file) {
286287

287288
@Override
288289
public void onError(File file, Exception e) {
289-
ToastUtils.show("下载出错:" + e.getMessage());
290+
ToastUtils.show(e.getMessage());
291+
if (e instanceof FileMD5Exception) {
292+
// 如果是文件 md5 校验失败,则删除文件
293+
file.delete();
294+
}
290295
}
291296

292297
@Override

app/src/main/java/com/hjq/easy/demo/http/model/RequestHandler.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.hjq.http.config.IRequestHandler;
2020
import com.hjq.http.exception.CancelException;
2121
import com.hjq.http.exception.DataException;
22+
import com.hjq.http.exception.FileMD5Exception;
2223
import com.hjq.http.exception.HttpException;
2324
import com.hjq.http.exception.NetworkException;
2425
import com.hjq.http.exception.NullBodyException;
@@ -61,9 +62,8 @@ public Object requestSucceed(@NonNull HttpRequest<?> httpRequest, @NonNull Respo
6162
}
6263

6364
if (!response.isSuccessful()) {
64-
// 返回响应异常
65-
throw new ResponseException(mApplication.getString(R.string.http_response_error) + ", responseCode: " +
66-
response.code() + ", message: " + response.message(), response);
65+
throw new ResponseException(String.format(mApplication.getString(R.string.http_response_error),
66+
response.code(), response.message()), response);
6767
}
6868

6969
if (Headers.class.equals(type)) {
@@ -171,6 +171,27 @@ public Exception requestFail(@NonNull HttpRequest<?> httpRequest, @NonNull Excep
171171
return new HttpException(e.getMessage(), e);
172172
}
173173

174+
@NonNull
175+
@Override
176+
public Exception downloadFail(@NonNull HttpRequest<?> httpRequest, @NonNull Exception e) {
177+
if (e instanceof ResponseException) {
178+
ResponseException responseException = ((ResponseException) e);
179+
Response response = responseException.getResponse();
180+
responseException.setMessage(String.format(mApplication.getString(R.string.http_response_error),
181+
response.code(), response.message()));
182+
return responseException;
183+
} else if (e instanceof NullBodyException) {
184+
NullBodyException nullBodyException = ((NullBodyException) e);
185+
nullBodyException.setMessage(mApplication.getString(R.string.http_response_null_body));
186+
return nullBodyException;
187+
} else if (e instanceof FileMD5Exception) {
188+
FileMD5Exception fileMd5Exception = ((FileMD5Exception) e);
189+
fileMd5Exception.setMessage(mApplication.getString(R.string.http_response_md5_error));
190+
return fileMd5Exception;
191+
}
192+
return requestFail(httpRequest, e);
193+
}
194+
174195
@Nullable
175196
@Override
176197
public Object readCache(@NonNull HttpRequest<?> httpRequest, @NonNull Type type, long cacheTime) {

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
<string name="http_data_explain_error">数据解析异常,请稍后</string>
99
<string name="http_server_out_time">服务器请求超时,请稍后再试</string>
1010
<string name="http_network_error">请求失败,请检查网络设置</string>
11-
<string name="http_response_error">服务器响应异常,请稍后再试</string>
11+
<string name="http_response_error">服务器响应异常,请稍后再试,响应码:%d,响应信息:%s</string>
1212
<string name="http_server_error">服务器连接异常,请稍后再试</string>
1313
<string name="http_request_cancel">请求被中断,请重试</string>
1414
<string name="http_response_null_body">服务器数据返回异常,请稍后再试</string>
15+
<string name="http_response_md5_error">下载失败,文件 md5 校验失败</string>
1516

1617
</resources>

library/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ android {
55

66
defaultConfig {
77
minSdkVersion 14
8-
versionCode 1100
9-
versionName "11.0"
8+
versionCode 1120
9+
versionName "11.2"
1010
}
1111

1212
// 使用 JDK 1.8

library/src/main/java/com/hjq/http/EasyConfig.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.hjq.http.config.IRequestServer;
77
import com.hjq.http.config.LogStrategy;
88
import com.hjq.http.config.RequestServer;
9+
import com.hjq.http.model.ThreadSchedulers;
910

1011
import java.net.MalformedURLException;
1112
import java.net.URL;
@@ -57,6 +58,9 @@ public static EasyConfig with(OkHttpClient client) {
5758
/** 通用请求头 */
5859
private HashMap<String, String> mHeaders;
5960

61+
/** 线程调度器 */
62+
private ThreadSchedulers mThreadSchedulers = ThreadSchedulers.MainThread;
63+
6064
/** 日志开关 */
6165
private boolean mLogEnabled = true;
6266
/** 日志 TAG */
@@ -144,6 +148,15 @@ public EasyConfig removeParam(String key) {
144148
return this;
145149
}
146150

151+
public EasyConfig setThreadSchedulers(ThreadSchedulers schedulers) {
152+
if (mThreadSchedulers == null) {
153+
// 线程调度器不能为空
154+
throw new NullPointerException("Thread schedulers cannot be empty");
155+
}
156+
mThreadSchedulers = schedulers;
157+
return this;
158+
}
159+
147160
public EasyConfig setLogStrategy(ILogStrategy strategy) {
148161
mLogStrategy = strategy;
149162
return this;
@@ -201,6 +214,10 @@ public HashMap<String, String> getHeaders() {
201214
return mHeaders;
202215
}
203216

217+
public ThreadSchedulers getThreadSchedulers() {
218+
return mThreadSchedulers;
219+
}
220+
204221
public ILogStrategy getLogStrategy() {
205222
return mLogStrategy;
206223
}
@@ -223,15 +240,15 @@ public long getRetryTime() {
223240

224241
public void into() {
225242
if (mClient == null) {
226-
throw new IllegalArgumentException("The OkHttp client object cannot be empty");
243+
throw new IllegalArgumentException("Please set up the OkHttpClient object");
227244
}
228245

229246
if (mServer == null) {
230-
throw new IllegalArgumentException("The host configuration cannot be empty");
247+
throw new IllegalArgumentException("Please set up the RequestServer object");
231248
}
232249

233250
if (mHandler == null) {
234-
throw new IllegalArgumentException("The object being processed by the request cannot be empty");
251+
throw new IllegalArgumentException("Please set the RequestHandler object");
235252
}
236253

237254
try {

0 commit comments

Comments
 (0)