Skip to content

Commit 4db8dec

Browse files
committed
修复上传 FileContentResolver 对象无法识别的问题
新增支持传入 FileContentResolver 文件名称参数 新增支持获取 FileContentResolver 的文件大小 修改 IRequestHandler.requestStart 方法参数类型 修改 FileWrapper 打开输入流和输出流的方法命名
1 parent d6faf05 commit 4db8dec

File tree

16 files changed

+315
-121
lines changed

16 files changed

+315
-121
lines changed

EasyHttp.apk

1.32 MB
Binary file not shown.

HelpDoc.md

Lines changed: 90 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
* [请求缓存](#请求缓存)
2828

29+
* [分区存储适配](#分区存储适配)
30+
2931
* [疑难解答](#疑难解答)
3032

3133
* [如何添加全局参数](#如何添加全局参数)
@@ -76,14 +78,14 @@
7678

7779
* [我想取消请求时显示的加载对话框该怎么办](#我想取消请求时显示的加载对话框该怎么办)
7880

81+
* [如何在 ViewModel 中使用 EasyHttp 请求网络](如何在-viewmodel-中使用-easyhttp-请求网络)
82+
7983
* [搭配 RxJava](#搭配-rxjava)
8084

8185
* [准备工作](#准备工作)
8286

8387
* [多个请求串行](#多个请求串行)
8488

85-
* [多个请求并行](#多个请求并行)
86-
8789
* [发起轮询请求](#发起轮询请求)
8890

8991
* [对返回的数据进行包装](#对返回的数据进行包装)
@@ -230,7 +232,7 @@ public final class LoginApi implements IRequestApi {
230232

231233
* @HttpIgnore:标记这个字段不会被发送给后台
232234

233-
* @HttpRename重新定义这个字段发送给后台的参数名称
235+
* @HttpRename重新定义这个字段发送给后台的参数或者请求头名称
234236

235237
* 可在这个类实现一些接口
236238

@@ -544,6 +546,37 @@ public class XxxServer implements IRequestServer {
544546
}
545547
```
546548

549+
#### 分区存储适配
550+
551+
* 在 Android 10 之前,我们在读写外部存储的时候,可以直接使用 File 对象来上传或者下载文件,但是在 Android 10 之后,如果你的项目需要 Android 10 分区存储的特性,那么在读写外部存储文件的时候,就不能直接使用 File 对象,因为 `ContentResolver.insert` 返回是一个 `Uri` 对象,这个时候就需要使用到 `FileContentResolver` 对象了(这个对象是 File 的子类),具体使用案例如下:
552+
553+
```java
554+
File outputFile;
555+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
556+
ContentValues values = new ContentValues();
557+
.........
558+
// 生成一个新的 uri 路径
559+
Uri outputUri = getContentResolver().insert(MediaStore.Xxx.Media.EXTERNAL_CONTENT_URI, values);
560+
// 适配 Android 10 分区存储特性
561+
outputFile = new FileContentResolver(context, outputUri);
562+
} else {
563+
outputFile = new File(xxxx);
564+
}
565+
566+
EasyHttp.post(this)
567+
.api(new XxxApi()
568+
.setImage(outputFile))
569+
.request(new HttpCallback<Xxx <Xxx>>(this) {
570+
571+
@Override
572+
public void onSucceed(Xxx<Xxx> data) {
573+
574+
}
575+
});
576+
```
577+
578+
* 这是上传的案例,下载也同理,这里不再赘述。
579+
547580
# 疑难解答
548581

549582
#### 如何添加全局参数
@@ -1224,6 +1257,58 @@ EasyHttp.post(this)
12241257
});
12251258
```
12261259

1260+
#### 如何在 ViewModel 中使用 EasyHttp 请求网络
1261+
1262+
* 第一步:封装一个 BaseViewModel,并将 LifecycleOwner 特性植入进去
1263+
1264+
```java
1265+
public class BaseViewModel extends ViewModel implements LifecycleOwner {
1266+
1267+
private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
1268+
1269+
public BaseViewModel() {
1270+
mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
1271+
mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
1272+
}
1273+
1274+
@Override
1275+
protected void onCleared() {
1276+
super.onCleared();
1277+
mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
1278+
}
1279+
1280+
@NonNull
1281+
@Override
1282+
public Lifecycle getLifecycle() {
1283+
return mLifecycle;
1284+
}
1285+
}
1286+
```
1287+
1288+
* 第二步:让业务 ViewModel 类继承至 BaseViewModel,具体案例如下
1289+
1290+
```java
1291+
public class XxxViewModel extends BaseViewModel {
1292+
1293+
public void xxxx() {
1294+
EasyHttp.post(this)
1295+
.api(new XxxApi())
1296+
.request(new OnHttpListener<HttpData<Xxx>>() {
1297+
1298+
@Override
1299+
public void onSucceed(HttpData<Xxx> result) {
1300+
1301+
}
1302+
1303+
@Override
1304+
public void onFail(Exception e) {
1305+
1306+
}
1307+
});
1308+
}
1309+
}
1310+
```
1311+
12271312
# 搭配 RxJava
12281313

12291314
#### 准备工作
@@ -1288,53 +1373,10 @@ Observable.create(new ObservableOnSubscribe<HttpData<SearchBean>>() {
12881373
});
12891374
```
12901375

1291-
#### 多个请求并行
1292-
1293-
```java
1294-
Observable.create(new ObservableOnSubscribe<IRequestApi>() {
1295-
1296-
@Override
1297-
public void subscribe(ObservableEmitter<IRequestApi> emitter) throws Exception {
1298-
SearchBlogsApi api1 = new SearchBlogsApi()
1299-
.setKeyword("1");
1300-
SearchBlogsApi api2 = new SearchBlogsApi()
1301-
.setKeyword("2");
1302-
1303-
emitter.onNext(api1);
1304-
emitter.onNext(api2);
1305-
emitter.onComplete();
1306-
}
1307-
})
1308-
.map(new Function<IRequestApi, HttpData<Void>>() {
1309-
1310-
@Override
1311-
public HttpData<Void> apply(IRequestApi api) throws Exception {
1312-
try {
1313-
return EasyHttp.post(MainActivity.this)
1314-
.api(api)
1315-
.execute(new ResponseClass<HttpData<Void>>() {});
1316-
} catch (Exception e) {
1317-
e.printStackTrace();
1318-
ToastUtils.show(e.getMessage());
1319-
throw e;
1320-
}
1321-
}
1322-
})
1323-
// 让被观察者执行在 IO 线程
1324-
.subscribeOn(Schedulers.io())
1325-
// 让观察者执行在主线程
1326-
.observeOn(AndroidSchedulers.mainThread())
1327-
.subscribe(new Consumer<HttpData<Void>>() {
1328-
1329-
@Override
1330-
public void accept(HttpData<Void> data) throws Exception {
1331-
Log.d("EasyHttp", "最终结果为:" + data.getMessage());
1332-
}
1333-
});
1334-
```
1335-
13361376
#### 发起轮询请求
13371377

1378+
* 如果轮询的次数是有限,可以考虑使用 Http 请求来实现,但是如果轮询的次数是无限的,那么不推荐使用 Http 请求来实现,应当使用 WebSocket 来做,又或者其他长链接协议来做。
1379+
13381380
```java
13391381
// 发起轮询请求,共发起三次请求,第一次请求在 5 秒后触发,剩下两次在 1 秒 和 2 秒后触发
13401382
Observable.intervalRange(1, 3, 5000, 1000, TimeUnit.MILLISECONDS)

README.md

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ android {
5252
5353
dependencies {
5454
// 网络请求框架:https://github.com/getActivity/EasyHttp
55-
implementation 'com.github.getActivity:EasyHttp:10.0'
55+
implementation 'com.github.getActivity:EasyHttp:10.2'
5656
// OkHttp 框架:https://github.com/square/okhttp
5757
// noinspection GradleDependency
5858
implementation 'com.squareup.okhttp3:okhttp:3.12.13'
@@ -65,9 +65,9 @@ dependencies {
6565

6666
| 功能或细节 | [EasyHttp](https://github.com/getActivity/EasyHttp) | [Retrofit](https://github.com/square/retrofit) | [OkGo](https://github.com/jeasonlzy/okhttp-OkGo) |
6767
| :----: | :------: | :-----: | :-----: |
68-
| 对应版本 | 10.0 | 2.9.0 | 3.0.4 |
68+
| 对应版本 | 10.2 | 2.9.0 | 3.0.4 |
6969
| 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) |
70-
| **aar 包大小** | 74 KB | 123 KB | 131 KB |
70+
| **aar 包大小** | 76 KB | 123 KB | 131 KB |
7171
| minSdk 要求 | API 14+ | API 21+ | API 14+ |
7272
| 配置多域名 ||||
7373
| **动态 Host** ||||
@@ -82,7 +82,8 @@ dependencies {
8282
| Json 参数提交 ||||
8383
| **请求代码定位** ||||
8484
| **延迟发起请求** ||||
85-
| 上传文件类型 | File / InputStream / RequestBody | RequestBody | File |
85+
| **分区存储适配** ||||
86+
| 上传文件类型 | File / FileContentResolver <br> InputStream / RequestBody | RequestBody | File |
8687
| **请求生命周期** | 自动管控 | 需要封装 | 需要封装 |
8788
| 参数传值方式 | 字段名 + 字段值 | 参数名 + 参数值 | 定义 Key + Value |
8889
| 框架灵活性 ||||
@@ -105,9 +106,39 @@ dependencies {
105106

106107
* EasyHttp 采用了 OOP 思想,一个请求代表一个对象,通过类继承和实现的特性来对接口进行动态化配置,几乎涵盖接口开发中所有的功能,使用起来非常简单灵活。而 Retrofit 采用的是注解方式,缺点是灵活性极低,因为注解上面只能放常量,也就会限定你在注解上面的一切参数只能是事先定义好的,这对接口的动态化配置极不利的。
107108

108-
* 有很多人觉得写一个接口类很麻烦,这个点确实有点麻烦,但是这块的付出是有收获的,从前期开发的效率考虑:OkGo > EasyHttp > Retrofit,但是从后期维护的效率考虑:EasyHttp > Retrofit > OkGo,之所以比较这三个框架,是因为框架的设计思想不同,但是我始终认为 EasyHttp 才是最好的设计,所以我创造了它。
109+
* 有很多人觉得写一个接口类很麻烦,关于这个问题我后面已经想到一个好方案了,大家可以将 Api 类和 Bean 类写在一起,这样大家就不需要多写一个类了,具体写法示例如下:
109110

110-
* 前期开发和后期维护哪个更重要?我觉得都重要,但是如果两者之间存在利益冲突,我会毫不犹豫地选择后期维护,因为前期开发占据的是小头,后期的持续维护才是大头。
111+
```java
112+
public final class XxxApi implements IRequestApi {
113+
114+
@Override
115+
public String getApi() {
116+
return "xxx/xxx";
117+
}
118+
119+
private int xxx;
120+
121+
public XxxApi setXxx(int xxx) {
122+
this.xxx = xxx;
123+
return this;
124+
}
125+
126+
......
127+
128+
public final static class Bean {
129+
130+
private int xyz;
131+
132+
public int getXyz() {
133+
return xyz;
134+
}
135+
136+
......
137+
}
138+
}
139+
```
140+
141+
* 是不是很机智?这样不仅很好地解决了这一问题,还能将一个接口所有的信息都包裹在这个类中,非常直观,一览如云,妥妥的一箭双雕。
111142

112143
#### 生命周期自动管控介绍
113144

app/build.gradle

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ android {
1111
applicationId 'com.hjq.easy.demo'
1212
minSdkVersion 16
1313
targetSdkVersion 30
14-
versionCode 1000
15-
versionName '10.0'
14+
versionCode 1020
15+
versionName '10.2'
1616
}
1717

1818
// 支持 JDK 1.8
@@ -60,8 +60,8 @@ dependencies {
6060

6161
implementation project(':library')
6262

63-
// AppCompat 库:https://developer.android.google.cn/jetpack/androidx/releases/appcompat?hl=zh-cn
64-
implementation 'androidx.appcompat:appcompat:1.3.0'
63+
// AndroidX 库:https://github.com/androidx/androidx
64+
implementation 'androidx.appcompat:appcompat:1.3.1'
6565

6666
// OkHttp 框架:https://github.com/square/okhttp
6767
// 升级注意事项:https://www.jianshu.com/p/d12d0f536f55
@@ -72,19 +72,22 @@ dependencies {
7272
implementation 'com.github.getActivity:ToastUtils:9.5'
7373

7474
// 权限请求框架:https://github.com/getActivity/XXPermissions
75-
implementation 'com.github.getActivity:XXPermissions:12.0'
75+
implementation 'com.github.getActivity:XXPermissions:12.3'
7676

7777
// 标题栏框架:https://github.com/getActivity/TitleBar
78-
implementation 'com.github.getActivity:TitleBar:8.6'
78+
implementation 'com.github.getActivity:TitleBar:9.2'
7979

8080
// Json 解析框架:https://github.com/google/gson
8181
implementation 'com.google.code.gson:gson:2.8.8'
8282
// Gson 解析容错:https://github.com/getActivity/GsonFactory
8383
implementation 'com.github.getActivity:GsonFactory:5.2'
8484

8585
// 日志调试框架:https://github.com/getActivity/Logcat
86-
debugImplementation 'com.github.getActivity:Logcat:9.8'
86+
debugImplementation 'com.github.getActivity:Logcat:9.9'
8787

8888
// 腾讯 MMKV:https://github.com/Tencent/MMKV
8989
implementation 'com.tencent:mmkv-static:1.2.10'
90+
91+
// 内存泄漏监测框架:https://github.com/square/leakcanary
92+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
9093
}

app/src/main/res/layout/activity_main.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<com.hjq.bar.TitleBar
1313
android:layout_width="wrap_content"
1414
android:layout_height="wrap_content"
15-
app:backButton="false"
15+
app:leftIcon="@null"
1616
app:title="https://github.com/getActivity/EasyHttp" />
1717

1818
<ProgressBar

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 1000
9-
versionName "10.0"
8+
versionCode 1020
9+
versionName "10.2"
1010
}
1111

1212
// 使用 JDK 1.8

0 commit comments

Comments
 (0)