112
112
113
113
* [ 对返回的数据进行包装] ( #对返回的数据进行包装 )
114
114
115
+ * [ 支持 Protobuf] ( #支持-protobuf )
116
+
117
+ * [ 准备工作] ( #准备工作 )
118
+
119
+ * [ 请求体解析成 Protobuf] ( #请求体解析成-protobuf )
120
+
121
+ * [ 响应体解析支持 Protobuf] ( #响应体解析支持-protobuf )
122
+
115
123
# 集成文档
116
124
117
125
#### 配置权限
@@ -365,7 +373,7 @@ EasyHttp.post(this)
365
373
}
366
374
367
375
@Override
368
- public void onUpdateFail (Exception e ) {
376
+ public void onUpdateFail (Throwable throwable ) {
369
377
toast(" 上传失败" );
370
378
}
371
379
@@ -410,8 +418,8 @@ EasyHttp.download(this)
410
418
}
411
419
412
420
@Override
413
- public void onDownloadFail (File file , Exception e ) {
414
- toast(" 下载出错:" + e . getMessage());
421
+ public void onDownloadFail (File file , Throwable throwable ) {
422
+ toast(" 下载出错:" + throwable . getMessage());
415
423
}
416
424
417
425
@Override
@@ -465,8 +473,8 @@ try {
465
473
.setKeyword(" 搬砖不再有" ))
466
474
.execute(new ResponseClass<HttpData<SearchBean > > () {});
467
475
toast(" 请求成功,请看日志" );
468
- } catch (Exception e ) {
469
- toast(e . getMessage());
476
+ } catch (Throwable throwable ) {
477
+ toast(throwable . getMessage());
470
478
}
471
479
```
472
480
@@ -647,8 +655,8 @@ lifecycleScope.launch(Dispatchers.IO) {
647
655
withContext(Dispatchers .Main ) {
648
656
// 在这里进行 UI 刷新
649
657
}
650
- } catch (e : Exception ) {
651
- toast(e .message)
658
+ } catch (throwable : Throwable ) {
659
+ toast(throwable .message)
652
660
}
653
661
}
654
662
```
@@ -991,6 +999,8 @@ public final class XxxApi implements IRequestApi {
991
999
992
1000
#### 如何传入请求头
993
1001
1002
+ * 给字段加上 ` @HttpHeader ` 注解即可,则表示这个字段是一个请求头,如果没有加上此注解,则框架默认将字段作为请求参数
1003
+
994
1004
``` java
995
1005
public final class XxxApi implements IRequestApi {
996
1006
@@ -1007,6 +1017,8 @@ public final class XxxApi implements IRequestApi {
1007
1017
1008
1018
#### 如何重命名参数或者请求头的名称
1009
1019
1020
+ * 给字段加上 ` @HttpRename ` 注解即可,则可以修改参数名的值,如果没有加上此注解,则框架默认使用字段名作为参数名
1021
+
1010
1022
``` java
1011
1023
public final class XxxApi implements IRequestApi {
1012
1024
@@ -1156,12 +1168,12 @@ EasyConfig.with(okHttpClient)
1156
1168
#### 如何取消已发起的请求
1157
1169
1158
1170
``` java
1159
- // 取消和这个 LifecycleOwner 关联的请求
1160
- EasyHttp . cancel( LifecycleOwner lifecycleOwner );
1171
+ // 根据 TAG 取消请求任务
1172
+ EasyHttp . cancelByTag( Object tag );
1161
1173
// 取消指定 Tag 标记的请求
1162
- EasyHttp . cancel (Object tag);
1174
+ EasyHttp . cancelByTag (Object tag);
1163
1175
// 取消所有请求
1164
- EasyHttp . cancel ();
1176
+ EasyHttp . cancelAll ();
1165
1177
```
1166
1178
1167
1179
#### 如何延迟发起一个请求
@@ -1296,7 +1308,7 @@ EasyHttp.post(ApplicationLifecycle.getInstance())
1296
1308
}
1297
1309
1298
1310
@Override
1299
- public void onHttpFail (Exception e ) {
1311
+ public void onHttpFail (Throwable throwable ) {
1300
1312
1301
1313
}
1302
1314
});
@@ -1307,7 +1319,7 @@ EasyHttp.post(ApplicationLifecycle.getInstance())
1307
1319
* 除了 Application,如果你在 Activity 或者 Service 中采用了 ApplicationLifecycle 的写法,那么为了避免内存泄漏或者崩溃的事情发生,需要你在请求的时候设置对应的 Tag,然后在恰当的时机手动取消请求(一般在 Activity 或者 Service 销毁或者退出的时候取消请求)。
1308
1320
1309
1321
``` java
1310
- EasyHttp . cancel (" abc" );
1322
+ EasyHttp . cancelByTag (" abc" );
1311
1323
```
1312
1324
1313
1325
#### 如何在 ViewModel 中使用 EasyHttp 请求网络
@@ -1354,7 +1366,7 @@ public class XxxViewModel extends BaseViewModel {
1354
1366
}
1355
1367
1356
1368
@Override
1357
- public void onHttpFail (Exception e ) {
1369
+ public void onHttpFail (Throwable throwable ) {
1358
1370
1359
1371
}
1360
1372
});
@@ -1401,7 +1413,7 @@ EasyHttp.post(this)
1401
1413
}
1402
1414
1403
1415
@Override
1404
- public void onHttpFail (Exception e ) {
1416
+ public void onHttpFail (Throwable throwable ) {
1405
1417
1406
1418
}
1407
1419
});
@@ -1419,7 +1431,7 @@ String json = gson.toJson(parameter);
1419
1431
1420
1432
EasyHttp . post(this )
1421
1433
.api(new XxxApi ())
1422
- .body(new JsonBody (json))
1434
+ .body(new JsonRequestBody (json))
1423
1435
.request(new HttpCallbackProxy<HttpData<Xxx > > (this ) {
1424
1436
1425
1437
@Override
@@ -1450,11 +1462,11 @@ parameter.put("key1", value1);
1450
1462
parameter. put(" key2" , value2);
1451
1463
1452
1464
String json = gson. toJson(parameter);
1453
- JsonBody jsonBody = new JsonBody (json)
1465
+ JsonRequestBody jsonRequestBody = new JsonRequestBody (json)
1454
1466
1455
1467
EasyHttp . post(this )
1456
1468
.api(new XxxApi ())
1457
- .body(jsonBody )
1469
+ .body(jsonRequestBody )
1458
1470
.request(new HttpCallbackProxy<HttpData<Xxx > > (this ) {
1459
1471
1460
1472
@Override
@@ -1655,8 +1667,12 @@ Observable.create(new ObservableOnSubscribe<HttpData<SearchBean>>() {
1655
1667
.api(new SearchBlogsApi ()
1656
1668
.setKeyword(" 搬砖不再有" ))
1657
1669
.execute(new ResponseClass<HttpData<SearchBean > > () {});
1658
- } catch (Exception e) {
1659
- throw e;
1670
+ } catch (Throwable throwable) {
1671
+ if (throwable instanceof Exception ) {
1672
+ throw (Exception ) throwable;
1673
+ } else {
1674
+ throw new RuntimeException (throwable);
1675
+ }
1660
1676
}
1661
1677
1662
1678
HttpData<SearchBean > data2;
@@ -1665,8 +1681,12 @@ Observable.create(new ObservableOnSubscribe<HttpData<SearchBean>>() {
1665
1681
.api(new SearchBlogsApi ()
1666
1682
.setKeyword(data1. getMessage()))
1667
1683
.execute(new ResponseClass<HttpData<SearchBean > > () {});
1668
- } catch (Exception e) {
1669
- throw e;
1684
+ } catch (Throwable throwable) {
1685
+ if (throwable instanceof Exception ) {
1686
+ throw (Exception ) throwable;
1687
+ } else {
1688
+ throw new RuntimeException (throwable);
1689
+ }
1670
1690
}
1671
1691
1672
1692
emitter. onNext(data2);
@@ -1740,9 +1760,9 @@ Observable.create(new ObservableOnSubscribe<HttpData<SearchBean>>() {
1740
1760
}
1741
1761
1742
1762
@Override
1743
- public void onHttpFail (Exception e ) {
1744
- super . onHttpFail(e );
1745
- emitter. onError(e );
1763
+ public void onHttpFail (Throwable throwable ) {
1764
+ super . onHttpFail(throwable );
1765
+ emitter. onError(throwable );
1746
1766
}
1747
1767
});
1748
1768
}
@@ -1764,7 +1784,7 @@ Observable.create(new ObservableOnSubscribe<HttpData<SearchBean>>() {
1764
1784
1765
1785
@Override
1766
1786
public void accept (String s ) throws Exception {
1767
- Log . i(" EasyHttp" , " " 当前页码位置" + s);
1787
+ Log . i(" EasyHttp" , " 当前页码位置" + s);
1768
1788
}
1769
1789
1770
1790
}, new Consumer<Throwable > () {
@@ -1774,4 +1794,193 @@ Observable.create(new ObservableOnSubscribe<HttpData<SearchBean>>() {
1774
1794
toast(throwable. getMessage());
1775
1795
}
1776
1796
});
1797
+ ```
1798
+
1799
+ # 支持 Protobuf
1800
+
1801
+ #### 准备工作
1802
+
1803
+ * 在项目根目录下得 ` build.gradle ` 文件加入以下配置
1804
+
1805
+ ``` groovy
1806
+ buildscript {
1807
+
1808
+ ......
1809
+
1810
+ dependencies {
1811
+ // 自动生成 Protobuf 类插件:https://github.com/google/protobuf-gradle-plugin
1812
+ classpath 'com.google.protobuf:protobuf-gradle-plugin:0.9.3'
1813
+ }
1814
+ }
1815
+ ```
1816
+
1817
+ * 在项目 app 模块下的 ` build.gradle ` 文件中加入远程依赖
1818
+
1819
+ ``` groovy
1820
+ ......
1821
+
1822
+ apply plugin: 'com.google.protobuf'
1823
+
1824
+ android {
1825
+ ......
1826
+
1827
+ sourceSets {
1828
+ main {
1829
+ proto {
1830
+ // 指定 Protobuf 文件路径
1831
+ srcDir 'src/main/proto'
1832
+ }
1833
+ }
1834
+ }
1835
+ }
1836
+
1837
+ protobuf {
1838
+
1839
+ protoc {
1840
+ // 也可以配置本地编译器路径
1841
+ artifact = 'com.google.protobuf:protoc:3.23.0'
1842
+ }
1843
+
1844
+ generateProtoTasks {
1845
+ all().each { task ->
1846
+ task.builtins {
1847
+ remove java
1848
+ }
1849
+ task.builtins {
1850
+ // 生产java源码
1851
+ java {}
1852
+ }
1853
+ }
1854
+ }
1855
+ }
1856
+
1857
+ dependencies {
1858
+
1859
+ ......
1860
+
1861
+ // Protobuf:https://github.com/protocolbuffers/protobuf
1862
+ implementation 'com.google.protobuf:protobuf-java:3.23.1'
1863
+ implementation 'com.google.protobuf:protoc:3.23.0'
1864
+ }
1865
+ ```
1866
+
1867
+ * 在 ` app/src/main/ ` 新建一个名为 ` proto ` 文件夹,用于存放 Protobuf 相关文件,然后创建 ` Person.proto ` 文件,具体内容如下:
1868
+
1869
+ ``` text
1870
+ syntax = "proto3";
1871
+ package tutorial;
1872
+
1873
+ message Person {
1874
+ string name = 1;
1875
+ int32 id = 2;
1876
+ string email = 3;
1877
+ string phone = 4;
1878
+ }
1879
+ ```
1880
+
1881
+ * 然后 ` Rebuild Project ` ,就能看到插件自动生成的 ` PersonOuterClass ` 类,` PersonOuterClass ` 类中还有一个名为 ` Person ` 的静态内部类
1882
+
1883
+ #### 请求体解析成 Protobuf
1884
+
1885
+ * 创建一个自定义的 RequestBody 类,用于将 Protocol 对象解析成流,建议存放在 ` com.xxx.xxx/http/model ` 包名下,
1886
+
1887
+ ``` java
1888
+ public class ProtocolRequestBody extends RequestBody {
1889
+
1890
+ /* * MessageLite 对象 */
1891
+ private final MessageLite mMessageLite;
1892
+ /* * 字节数组 */
1893
+ private final byte [] mBytes;
1894
+
1895
+ public ProtocolRequestBody (MessageLite messageLite ) {
1896
+ mMessageLite = messageLite;
1897
+ mBytes = messageLite. toByteArray();
1898
+ }
1899
+
1900
+ @Override
1901
+ public MediaType contentType () {
1902
+ return ContentType . JSON ;
1903
+ }
1904
+
1905
+ @Override
1906
+ public long contentLength () {
1907
+ // 需要注意:这里需要用字节数组的长度来计算
1908
+ return mBytes. length;
1909
+ }
1910
+
1911
+ @Override
1912
+ public void writeTo (BufferedSink sink ) throws IOException {
1913
+ sink. write(mBytes, 0 , mBytes. length);
1914
+ }
1915
+
1916
+ @NonNull
1917
+ @Override
1918
+ public String toString () {
1919
+ return mMessageLite. toString();
1920
+ }
1921
+
1922
+ /**
1923
+ * 获取 MessageLite 对象
1924
+ */
1925
+ @NonNull
1926
+ public MessageLite getMessageLite () {
1927
+ return mMessageLite;
1928
+ }
1929
+ }
1930
+ ```
1931
+
1932
+ * 发起请求示例
1933
+
1934
+ ``` java
1935
+ // 假装生成一个 Protobuf 对象
1936
+ Person person = Person . parseFrom(" xxxxxxxxx" . getBytes());
1937
+
1938
+ EasyHttp . post(this )
1939
+ .api(new XxxApi ())
1940
+ .body(new ProtocolRequestBody (person))
1941
+ .request(new HttpCallbackProxy<HttpData<SearchBlogsApi . Bean > >(this ) {
1942
+
1943
+ @Override
1944
+ public void onHttpSuccess (HttpData<SearchBlogsApi . Bean > result ) {
1945
+
1946
+ }
1947
+ });
1948
+ ```
1949
+
1950
+ #### 响应体解析支持 Protobuf
1951
+
1952
+ * 这个支持很简单了,只需要修改 ` IRequestHandler ` 接口的实现即可,具体的代码实现如下:
1953
+
1954
+ ```
1955
+ public final class RequestHandler implements IRequestHandler {
1956
+
1957
+ ......
1958
+
1959
+ @NonNull
1960
+ @Override
1961
+ public Object requestSuccess(@NonNull HttpRequest<?> httpRequest, @NonNull Response response,
1962
+ @NonNull Type type) throws Throwable {
1963
+ ......
1964
+
1965
+ final Object result;
1966
+
1967
+ try {
1968
+ if (type instanceof Class<?> && AbstractParser.class.isAssignableFrom((Class<?>) type)) {
1969
+ String simpleName = ((Class<?>) type).getSimpleName();
1970
+ Class<?> clazz = Class.forName("tutorial." + simpleName + ".OuterClass." + simpleName);
1971
+ Method parseFromMethod = clazz.getMethod("parseFrom", byte[].class);
1972
+ // 调用静态方法
1973
+ result = parseFromMethod.invoke(null, (Object) text.getBytes());
1974
+ } else {
1975
+ result = GsonFactory.getSingletonGson().fromJson(text, type);
1976
+ }
1977
+ } catch (JsonSyntaxException e) {
1978
+ // 返回结果读取异常
1979
+ throw new DataException(mApplication.getString(R.string.http_data_explain_error), e);
1980
+ }
1981
+
1982
+ ......
1983
+ return result;
1984
+ }
1985
+ }
1777
1986
```
0 commit comments