上节讲述了Retrofit的基本使用,本章节讲述Retrofit结合OkHttp,RxJava,RxAndroid使用讲解。
Retrofit基础讲解(上)
Retrofit基础讲解(上)_jianning-wu的博客-CSDN博客
Retrofit基础讲解(下)
Retrofit基础讲解(下)_数组 链表 字典的区别_jianning-wu的博客-CSDN博客
RxJava系列
https://blog.csdn.net/weixin_37730482/category_10501619.html
一.简介
单单引入Retrofit其实已经包含了一部分OkHttp的Jar包。也可以完全完成网络的请求。那么为什么要结合OkHttp使用呢?因为OkHttp可以设置很多。比如拦截器,比如实现Https,比如Cookie的管理等等。
而引入RxJava和RxAndroid是为了更好地完成线程切换。
二.具体实现
1.注意:
依赖Retrofit的组合API时,需要依赖很多包。比如Retrofit的RxJava的依赖。此时项目中如果已经依赖了RxJava。可能就会有依赖冲突问题。
问题描述
More than one file was found with OS independent path 'META-INF/rxjava.properties'.
问题原因
因为项目本身有一个RxJava的单独依赖,Retrofit的RxJava也是一个RxJava依赖,所以会冲突
Retrofit的RxJava依赖生成Jar包
也就是说Retrofit的RxJava不仅下载了Retrofit的adapter的RxJava,也会下载一个单独的RxJava包。
然后项目中本身也有一个RxJava的依赖。
implementation 'io.reactivex:rxjava:1.3.2'
下载的Jar包
所以会有冲突。
问题解决
<1> Gradle配置忽略冲突
defaultConfig {
applicationId "com.wjn.networkdemo"
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "1.0"
packagingOptions {
//解决编译时com.android.builder.merge.DuplicateRelativeFileException: More than one file was found with OS independent path 'META-INF/rxjava.properties'这个错误
exclude 'META-INF/rxjava.properties'
}
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
<2> Retrofit的RxJava依赖修改
修改前
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
修改后
//Retrofit支持RxJava方式回调
implementation ('com.squareup.retrofit2:adapter-rxjava2:2.3.0'){
exclude group: "io.reactivex.rxjava2", module: "rxjava"
}
修改后
以上Jar消失,编译成功。
<dependency>
<groupId>io.reactivex.rxjava2</groupId>
<artifactId>rxjava</artifactId>
</dependency>
group取值:上述groupId值
module取值:上述artifactId值
2.Gradle依赖
//OkHttp
implementation 'com.squareup.okhttp3:okhttp:3.9.0'
//RxJava
implementation 'io.reactivex.rxjava2:rxjava:2.0.1'
//RxAndroid
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
//Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.7.0'
//Retrofit支持RxJava方式回调 忽略此包的下载 避免RxJavaJar包重复
implementation ('com.squareup.retrofit2:adapter-rxjava2:2.3.0'){
exclude group: "io.reactivex.rxjava2", module: "rxjava"
}
3.接口
package com.wjn.networkdemo.retrofit.rx;
import io.reactivex.Observable;
import okhttp3.ResponseBody;
import retrofit2.http.GET;
public interface FanYiRxService {
/**
* 翻译模块Get请求
*
* @return Observable
*/
@GET("openapi.do?keyfrom=imoocdict123456&key=324273592&type=data&doctype=json&version=1.1&q=blue")
Observable<ResponseBody> getFanYiByGet();
}
使用RxJava后,返回值变成Observable(被观察者) 注意依赖的RxJava必须要和Retrofit的RxJava版本一致(比如都是2.XXX),否则报错。
即
单独的RxJava
implementation 'io.reactivex.rxjava2:rxjava:2.0.1'
Retrofit的RxJava
implementation ('com.squareup.retrofit2:adapter-rxjava2:2.3.0'){
exclude group: "io.reactivex.rxjava2", module: "rxjava"
}
4.测试类
package com.wjn.networkdemo.retrofit.rx;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import com.wjn.networkdemo.R;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
public class RetrofitRxActivity extends AppCompatActivity {
private Retrofit mRetrofit;
private FanYiRxService mFanYiRxService;
private String mBaseUrl = "http://fanyi.youdao.com/";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_retrofit_rx);
//配置okHttp的参数
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(3000, TimeUnit.SECONDS)
.build();
//获取Retrofit对象
mRetrofit = new Retrofit.Builder()
.baseUrl(mBaseUrl)//设置BaseUrl 必须以'/'结尾
.client(okHttpClient)//设置使用OkHttp请求
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//配置回调库,采用RxJava
.build();
//IO线程请求数据 UI线程更新数据
findViewById(R.id.activity_retrofit_rx_textview1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getData();
}
});
//IO线程请求数据 子线程更新数据
findViewById(R.id.activity_retrofit_rx_textview2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getDataNew();
}
});
}
/**
* Retrofit Get请求
* 被观察者 IO线程 请求接口
* 观察者 UI线程 更新UI
*/
private void getData() {
if (null != mRetrofit) {
mFanYiRxService = mRetrofit.create(FanYiRxService.class);
mFanYiRxService.getFanYiByGet()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ResponseBody>() {
@Override
public void onComplete() {
Log.d("RetrofitRxActivity", "onComplete方法");
Log.d("RetrofitRxActivity", "onComplete方法 线程----:" + Thread.currentThread().getName());
}
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(ResponseBody value) {
if (null == value) return;
String result = null;
try {
result = value.string();
} catch (IOException e) {
e.printStackTrace();
}
Log.d("RetrofitRxActivity", "onNext方法 result----:" + result);
Log.d("RetrofitRxActivity", "onNext方法 线程----:" + Thread.currentThread().getName());
}
@Override
public void onError(Throwable e) {
Log.d("RetrofitRxActivity", "onError方法e.toString()----:" + e.toString());
Log.d("RetrofitRxActivity", "onError方法 线程----:" + Thread.currentThread().getName());
}
});
}
}
/**
* Retrofit Get请求
* 被观察者 IO线程 请求接口
* 观察者 子线程 更新UI
*/
private void getDataNew() {
if (null != mRetrofit) {
mFanYiRxService = mRetrofit.create(FanYiRxService.class);
mFanYiRxService.getFanYiByGet()
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.subscribe(new Observer<ResponseBody>() {
@Override
public void onComplete() {
Log.d("RetrofitRxActivity", "onComplete方法");
Log.d("RetrofitRxActivity", "onComplete方法 线程----:" + Thread.currentThread().getName());
}
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(ResponseBody value) {
if (null == value) return;
String result = null;
try {
result = value.string();
} catch (IOException e) {
e.printStackTrace();
}
Log.d("RetrofitRxActivity", "onNext方法 result----:" + result);
Log.d("RetrofitRxActivity", "onNext方法 线程----:" + Thread.currentThread().getName());
}
@Override
public void onError(Throwable e) {
Log.d("RetrofitRxActivity", "onError方法e.toString()----:" + e.toString());
Log.d("RetrofitRxActivity", "onError方法 线程----:" + Thread.currentThread().getName());
}
});
}
}
}
5.结果
<1> IO线程请求 UI线程更新
D/RetrofitRxActivity: onNext方法 result----:{"translation":["蓝色的"],"basic":{"us-phonetic":"bluː","phonetic":"bluː","uk-phonetic":"bluː","explains":["adj. 蓝色的;忧郁的,悲观的;(由于冷或呼吸困难)发青的,青紫的;(电影、玩笑或故事)色情的,黄色的;(肉)未熟的;(政治上)保守的","n. 蓝色;蓝色物品;(牛津或剑桥大学的运动员)蓝色荣誉者;失误;红发人;打架","vt. (使)变成蓝色;把......染成蓝色;给\u2026\u2026上蓝色漂白剂;挥霍(钱财)","n. (Blue) (英、美、加、澳、新)布卢(人名)"]},"query":"blue","errorCode":0,"web":[{"value":["蓝色的","蓝色","刀枪不入"],"key":"blue"},{"value":["钴蓝色","艳蓝色","钴蓝","群青"],"key":"Cobalt blue"},{"value":["蓝月","蓝月亮","千载难逢的时机","蓝色月亮"],"key":"Blue Moon"}]}
D/RetrofitRxActivity: onNext方法 线程----:main
D/RetrofitRxActivity: onComplete方法
D/RetrofitRxActivity: onComplete方法 线程----:main
<2> IO线程请求 子线程更新
D/RetrofitRxActivity: onNext方法 result----:{"translation":["蓝色的"],"basic":{"us-phonetic":"bluː","phonetic":"bluː","uk-phonetic":"bluː","explains":["adj. 蓝色的;忧郁的,悲观的;(由于冷或呼吸困难)发青的,青紫的;(电影、玩笑或故事)色情的,黄色的;(肉)未熟的;(政治上)保守的","n. 蓝色;蓝色物品;(牛津或剑桥大学的运动员)蓝色荣誉者;失误;红发人;打架","vt. (使)变成蓝色;把......染成蓝色;给\u2026\u2026上蓝色漂白剂;挥霍(钱财)","n. (Blue) (英、美、加、澳、新)布卢(人名)"]},"query":"blue","errorCode":0,"web":[{"value":["蓝色的","蓝色","刀枪不入"],"key":"blue"},{"value":["钴蓝色","艳蓝色","钴蓝","群青"],"key":"Cobalt blue"},{"value":["蓝月","蓝月亮","千载难逢的时机","蓝色月亮"],"key":"Blue Moon"}]}
D/RetrofitRxActivity: onNext方法 线程----:RxNewThreadScheduler-1
D/RetrofitRxActivity: onComplete方法
D/RetrofitRxActivity: onComplete方法 线程----:RxNewThreadScheduler-1