112112
113113 * [ 对返回的数据进行包装] ( #对返回的数据进行包装 )
114114
115+ * [ 支持 Protobuf] ( #支持-protobuf )
116+
117+ * [ 准备工作] ( #准备工作 )
118+
119+ * [ 请求体解析成 Protobuf] ( #请求体解析成-protobuf )
120+
121+ * [ 响应体解析支持 Protobuf] ( #响应体解析支持-protobuf )
122+
115123# 集成文档
116124
117125#### 配置权限
@@ -365,7 +373,7 @@ EasyHttp.post(this)
365373 }
366374
367375 @Override
368- public void onUpdateFail (Exception e ) {
376+ public void onUpdateFail (Throwable throwable ) {
369377 toast(" 上传失败" );
370378 }
371379
@@ -410,8 +418,8 @@ EasyHttp.download(this)
410418 }
411419
412420 @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());
415423 }
416424
417425 @Override
@@ -465,8 +473,8 @@ try {
465473 .setKeyword(" 搬砖不再有" ))
466474 .execute(new ResponseClass<HttpData<SearchBean > > () {});
467475 toast(" 请求成功,请看日志" );
468- } catch (Exception e ) {
469- toast(e . getMessage());
476+ } catch (Throwable throwable ) {
477+ toast(throwable . getMessage());
470478}
471479```
472480
@@ -647,8 +655,8 @@ lifecycleScope.launch(Dispatchers.IO) {
647655 withContext(Dispatchers .Main ) {
648656 // 在这里进行 UI 刷新
649657 }
650- } catch (e : Exception ) {
651- toast(e .message)
658+ } catch (throwable : Throwable ) {
659+ toast(throwable .message)
652660 }
653661}
654662```
@@ -991,6 +999,8 @@ public final class XxxApi implements IRequestApi {
991999
9921000#### 如何传入请求头
9931001
1002+ * 给字段加上 ` @HttpHeader ` 注解即可,则表示这个字段是一个请求头,如果没有加上此注解,则框架默认将字段作为请求参数
1003+
9941004``` java
9951005public final class XxxApi implements IRequestApi {
9961006
@@ -1007,6 +1017,8 @@ public final class XxxApi implements IRequestApi {
10071017
10081018#### 如何重命名参数或者请求头的名称
10091019
1020+ * 给字段加上 ` @HttpRename ` 注解即可,则可以修改参数名的值,如果没有加上此注解,则框架默认使用字段名作为参数名
1021+
10101022``` java
10111023public final class XxxApi implements IRequestApi {
10121024
@@ -1156,12 +1168,12 @@ EasyConfig.with(okHttpClient)
11561168#### 如何取消已发起的请求
11571169
11581170``` java
1159- // 取消和这个 LifecycleOwner 关联的请求
1160- EasyHttp . cancel( LifecycleOwner lifecycleOwner );
1171+ // 根据 TAG 取消请求任务
1172+ EasyHttp . cancelByTag( Object tag );
11611173// 取消指定 Tag 标记的请求
1162- EasyHttp . cancel (Object tag);
1174+ EasyHttp . cancelByTag (Object tag);
11631175// 取消所有请求
1164- EasyHttp . cancel ();
1176+ EasyHttp . cancelAll ();
11651177```
11661178
11671179#### 如何延迟发起一个请求
@@ -1296,7 +1308,7 @@ EasyHttp.post(ApplicationLifecycle.getInstance())
12961308 }
12971309
12981310 @Override
1299- public void onHttpFail (Exception e ) {
1311+ public void onHttpFail (Throwable throwable ) {
13001312
13011313 }
13021314 });
@@ -1307,7 +1319,7 @@ EasyHttp.post(ApplicationLifecycle.getInstance())
13071319* 除了 Application,如果你在 Activity 或者 Service 中采用了 ApplicationLifecycle 的写法,那么为了避免内存泄漏或者崩溃的事情发生,需要你在请求的时候设置对应的 Tag,然后在恰当的时机手动取消请求(一般在 Activity 或者 Service 销毁或者退出的时候取消请求)。
13081320
13091321``` java
1310- EasyHttp . cancel (" abc" );
1322+ EasyHttp . cancelByTag (" abc" );
13111323```
13121324
13131325#### 如何在 ViewModel 中使用 EasyHttp 请求网络
@@ -1354,7 +1366,7 @@ public class XxxViewModel extends BaseViewModel {
13541366 }
13551367
13561368 @Override
1357- public void onHttpFail (Exception e ) {
1369+ public void onHttpFail (Throwable throwable ) {
13581370
13591371 }
13601372 });
@@ -1401,7 +1413,7 @@ EasyHttp.post(this)
14011413 }
14021414
14031415 @Override
1404- public void onHttpFail (Exception e ) {
1416+ public void onHttpFail (Throwable throwable ) {
14051417
14061418 }
14071419 });
@@ -1419,7 +1431,7 @@ String json = gson.toJson(parameter);
14191431
14201432EasyHttp . post(this )
14211433 .api(new XxxApi ())
1422- .body(new JsonBody (json))
1434+ .body(new JsonRequestBody (json))
14231435 .request(new HttpCallbackProxy<HttpData<Xxx > > (this ) {
14241436
14251437 @Override
@@ -1450,11 +1462,11 @@ parameter.put("key1", value1);
14501462parameter. put(" key2" , value2);
14511463
14521464String json = gson. toJson(parameter);
1453- JsonBody jsonBody = new JsonBody (json)
1465+ JsonRequestBody jsonRequestBody = new JsonRequestBody (json)
14541466
14551467EasyHttp . post(this )
14561468 .api(new XxxApi ())
1457- .body(jsonBody )
1469+ .body(jsonRequestBody )
14581470 .request(new HttpCallbackProxy<HttpData<Xxx > > (this ) {
14591471
14601472 @Override
@@ -1655,8 +1667,12 @@ Observable.create(new ObservableOnSubscribe<HttpData<SearchBean>>() {
16551667 .api(new SearchBlogsApi ()
16561668 .setKeyword(" 搬砖不再有" ))
16571669 .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+ }
16601676 }
16611677
16621678 HttpData<SearchBean > data2;
@@ -1665,8 +1681,12 @@ Observable.create(new ObservableOnSubscribe<HttpData<SearchBean>>() {
16651681 .api(new SearchBlogsApi ()
16661682 .setKeyword(data1. getMessage()))
16671683 .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+ }
16701690 }
16711691
16721692 emitter. onNext(data2);
@@ -1740,9 +1760,9 @@ Observable.create(new ObservableOnSubscribe<HttpData<SearchBean>>() {
17401760 }
17411761
17421762 @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 );
17461766 }
17471767 });
17481768 }
@@ -1764,7 +1784,7 @@ Observable.create(new ObservableOnSubscribe<HttpData<SearchBean>>() {
17641784
17651785 @Override
17661786 public void accept (String s ) throws Exception {
1767- Log . i(" EasyHttp" , " " 当前页码位置" + s);
1787+ Log . i(" EasyHttp" , " 当前页码位置" + s);
17681788 }
17691789
17701790}, new Consumer<Throwable > () {
@@ -1774,4 +1794,193 @@ Observable.create(new ObservableOnSubscribe<HttpData<SearchBean>>() {
17741794 toast(throwable. getMessage());
17751795 }
17761796});
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+ }
17771986```
0 commit comments