本文使用登录场景来简单介绍 Android 应用中使用 OkHttp + Retrofit + RxJava 访问网络的用法。
- 数据交换协议 HTTP
- 数据交换格式 JSON
- HTTP 请求方法 POST
使用 HTTP 访问网络的准备工作,参见Android 访问网络:方案一 OkHttp一文访问网络的准备工作部分。
使用 OkHttp + Retrofit + RxJava 访问网络
1. 引入依赖
build.gradle(:app)
dependencies {
...
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.14.9'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'
}
2. 定义网络访问接口
创建 UserService 接口,用来提供 User 模块的网络访问服务。
UserService.java
public interface UserService {
@POST("user/login")
Single<Result<String>> login(@Body LoginParam loginParam);
}
Single
是 RxJava 中的一种可观察对象类。Retrofit 为我们创建该类的实例后,即可调用 subscribe()
方法发起 HTTP 请求,然后在 SingleObserver
中处理请求结果。
有些关于 OkHttp + Retrofit + RxJava 的文章中在这里会使用 Observable
和 Observer
。
它们两者的区别如下:
- Single 只发射一个值,或者一个错误通知。
- Observable 可以发射 0 或多个值和一个结束通知,或者一个错误通知。
HTTP 请求场景可能需要处理的结果有两种:一是请求成功,顺利和服务端交换了数据;二是请求失败。
如果把处理 HTTP 请求结果比作削苹果,那么使用 Single 类似于使用水果刀;而 Observable 更像是使用菜刀。
总的来说,Single 就像是为这个场景量身打造的,而 Observable 则更加通用。都能胜任这个任务,至于选择,就看个人喜好吧。
关于 Result 类和方法注解的介绍,参见Android 访问网络:方案二 OkHttp + Retrofit一文的使用 OkHttp + Retrofit 访问网络-2.定义网络访问接口部分。
3. 创建 Retrofit 实例
- 创建 OkHttp 实例,添加日志拦截器,以便调试。
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
- 创建 Retrofit 实例,配置 baseUrl , 添加 ConverterFactory 和 CallAdapterFactory 。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.43.218:8080/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.client(client)
.build();
4. 创建 Service 实例
UserService userService = retrofit.create(UserService.class);
5. 创建 Single 实例
Single<Result<String>> single = userService.login(new LoginParam(userName, password));
由于这一步比较简单,通常的写法是和下一步连起来,将 Single 的实例作为匿名对象来使用。
userService.login(new LoginParam(userName, password))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleObserver<Result<String>>() {...});
6. 向服务端发送 HTTP 请求
创建 SingleObserver 实例,用于处理网络访问结果。
single.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new SingleObserver<Result<String>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onSuccess(@NonNull Result<String> result) {
}
@Override
public void onError(@NonNull Throwable e) {
}
});
-
subscribeOn(Schedulers.io())
在 IO 线程发送 HTTP 请求 -
observeOn(AndroidSchedulers.mainThread())
在主线程处理请求结果 -
onSubscribe()
当即将发送请求时调用 -
onSuccess()
当请求成功时调用 -
onError()
当请求失败时调用
注:此处的成功和失败是 HTTP 数据交换层面的意义。成功指的是 APP 和服务端顺利交换了数据。例如不论 APP 接收到的响应数据是{ "code": 600, "message": "登录成功", "data": "token" }
还是{ "code": 701, "message": "密码错误", "data": "" }
,都是请求成功,会执行onSuccess()
方法。当无法和服务端交换数据时,则会执行onError()
方法。
7. 在 SingleObserver 的 onSuccess() 中处理网络访问结果
@Override
public void onSuccess(@NonNull Result<String> result) {
Toast.makeText(LoginActivity.this, result.message, Toast.LENGTH_SHORT).show();
if (result.isSuccessful()) {
Log.i(TAG, "token : " + result.data);
// save token
// start activity
}
}
附
测试设备参数
- 型号:vivo Y66L
- 操作系统:Funtouch OS 3.0(Android 6.0.1)