最近在整理 Retrofit 和 Rxjava 的知识,前面几篇文章分别整理了 Rxjava 和 Retrofit 现在就来整理一下 Retrofit 和 Rxjava的连用。知道了Retrofit 和 Rxjava 的单独用法,连用其实很简单。在Retrofit的基础上改。
不一样的地方有如下几点:
第一,导的包不一样
Retrofit中:
compile 'com.squareup.retrofit2:retrofit:2.2.0'// Retrofit库
compile 'com.squareup.retrofit2:converter-gson:2.3.0'//返回的数据是json的,用到了gson解析
Retrofit 和 Rxjava连用中
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation 'io.reactivex.rxjava2:rxjava:2.x.y'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'//转换器,请求结果转换成Model
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'//配合Rxjava 使用
第二,创建用于 描述网络请求的接口的时候,方法返回值类型的改变。由Retrofit中的 Call<T> 变成了 Observable<T>,代码如下:
Retrofit中:
/**
* 创建 用于描述网络请求 的接口
* Retrofit将 Http请求 抽象成 Java接口:采用 注解 描述网络请求参数 和配置网络请求参数
*/
public interface ApiService {
//测试 get
@GET("ajax.php?a=fy&f=auto&t=auto&w=hello")
Call<ResponseInfo> testGet();
//测试 post
@POST("ajax.php?a=fy&f=auto&t=auto")
Call<ResponseInfo> testPost(@Query("w") String w);
//测试 下载文件
@Streaming
@GET
Call<ResponseBody> testDownload(@Url String fileUrl);
}
Retrofit 和 Rxjava连用中
/**
* 创建 用于描述网络请求 的接口
* Retrofit将 Http请求 抽象成 Java接口:采用 注解 描述网络请求参数 和配置网络请求参数
*/
public interface ApiService {
//测试 get
@GET("ajax.php?a=fy&f=auto&t=auto&w=hello")
Observable<ResponseInfo> testGet();
//测试 post
@POST("ajax.php?a=fy&f=auto&t=auto")
Observable<ResponseInfo> testPost(@Query("w") String w);
//测试 下载文件
@Streaming
@GET
Observable<ResponseBody> testDownload(@Url String fileUrl);
}
第三,创建Retrofit实例的时候需要加上addCallAdapterFactory(RxJava2CallAdapterFactory.create()),代码如下。
Retrofit中:
retrofit = new Retrofit.Builder()
.baseUrl("http://fy.iciba.com/") // 设置 网络请求 Url
.addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析(记得加入依赖)
.build();
Retrofit 和 Rxjava连用中:
retrofit = new Retrofit.Builder()
.baseUrl("http://fy.iciba.com/") // 设置 网络请求 Url
.addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析(记得加入依赖)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
第三,网络请求方式不一样
Retrofit中:
ApiService request = retrofit.create(ApiService.class);
Call<ResponseInfo> call = request.testGet();// 封装请求
call.enqueue(new Callback<ResponseInfo>() {// 发送网络请求(异步)
@Override
public void onResponse(Call<ResponseInfo> call, Response<ResponseInfo> response) {//主线程中调用
ResponseInfo body = response.body();
Log.i("gao", "测试 get body = " + body + " 线程名字 = " + Thread.currentThread().getName());
Toast.makeText(MainActivity.this, "测试GET= " + body.content.word_mean.get(0), Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Call<ResponseInfo> call, Throwable t) {//主线程中调用
Log.i("gao", " testGet onFailure " + " 线程名字 = " + Thread.currentThread().getName());
Toast.makeText(MainActivity.this, " testGet onFailure ", Toast.LENGTH_SHORT).show();
}
});
Retrofit 和 Rxjava连用中:
ApiService request = retrofit.create(ApiService.class);
Observable<ResponseInfo> observable = request.testGet();// 封装请求
observable.subscribeOn(Schedulers.io())//网络请求发生在 子线程
.observeOn(AndroidSchedulers.mainThread())//请求回调发生在 主线程
.subscribe(new Observer<ResponseInfo>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(ResponseInfo responseInfo) {
Log.i("gao", "测试 get body = " + responseInfo + " 线程名字 = " + Thread.currentThread().getName());
Toast.makeText(MainActivity.this, "测试GET= " + responseInfo.content.word_mean.get(0), Toast.LENGTH_SHORT).show();
}
@Override
public void onError(Throwable e) {
Log.i("gao", " testGet onFailure " + " 线程名字 = " + Thread.currentThread().getName());
Toast.makeText(MainActivity.this, " testGet onFailure ", Toast.LENGTH_SHORT).show();
}
@Override
public void onComplete() {
}
});
demo中和上篇文章一样写了 怎么请求 get post 和 怎么下载文件,的方法,这里是MainActivity的代码。如果需要完整的代码,在博客的最后有下载的方法。
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
public class MainActivity extends Activity implements View.OnClickListener {
Retrofit retrofit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.testGet).setOnClickListener(this);
findViewById(R.id.testPost).setOnClickListener(this);
findViewById(R.id.testLoaddown).setOnClickListener(this);
// 创建Retrofit实例时需要通过Retrofit.Builder,并调用baseUrl方法设置URL。Retrofit2的baseUlr 必须以 /(斜线)结束,不然会抛出一个IllegalArgumentException
retrofit = new Retrofit.Builder()
.baseUrl("http://fy.iciba.com/") // 设置 网络请求 Url
.addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析(记得加入依赖)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
//动态获取权限
AppPermission.isGrantExternalRW(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.testGet:
testGet();
break;
case R.id.testPost:
testPost("hello");
break;
case R.id.testLoaddown:
if (AppPermission.isGrantExternalRW(this)) {
String url = "http://imtt.dd.qq.com/16891/89E1C87A75EB3E1221F2CDE47A60824A.apk?fsname=com.snda.wifilocating_4.2.62_3192.apk&csr=1bbd";
testLoaddown(Environment.getExternalStorageDirectory() + "/ceshi.apk", url);
}
break;
}
}
public void testGet() {
ApiService request = retrofit.create(ApiService.class);
Observable<ResponseInfo> observable = request.testGet();// 封装请求
observable.subscribeOn(Schedulers.io())//网络请求发生在 子线程
.observeOn(AndroidSchedulers.mainThread())//请求回调发生在 主线程
.subscribe(new Observer<ResponseInfo>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(ResponseInfo responseInfo) {
Log.i("gao", "测试 get body = " + responseInfo + " 线程名字 = " + Thread.currentThread().getName());
Toast.makeText(MainActivity.this, "测试GET= " + responseInfo.content.word_mean.get(0), Toast.LENGTH_SHORT).show();
}
@Override
public void onError(Throwable e) {
Log.i("gao", " testGet onFailure " + " 线程名字 = " + Thread.currentThread().getName());
Toast.makeText(MainActivity.this, " testGet onFailure ", Toast.LENGTH_SHORT).show();
}
@Override
public void onComplete() {
}
});
}
public void testPost(String string) {
ApiService request = retrofit.create(ApiService.class);
Observable<ResponseInfo> observable = request.testPost(string);// 封装请求
observable.subscribeOn(Schedulers.io())//网络请求在子线程
.observeOn(AndroidSchedulers.mainThread())//请求回调在主线程
.subscribe(new Observer<ResponseInfo>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(ResponseInfo responseInfo) {
Log.i("gao", "测试 post body = " + responseInfo + " 线程名字 = " + Thread.currentThread().getName());
Toast.makeText(MainActivity.this, "测试 post body = " + responseInfo, Toast.LENGTH_SHORT).show();
}
@Override
public void onError(Throwable e) {
Log.i("gao", "testPost onFailure " + " 线程名字 = " + Thread.currentThread().getName());
Toast.makeText(MainActivity.this, "testPost onFailure ", Toast.LENGTH_SHORT).show();
}
@Override
public void onComplete() {
}
});
}
public void testLoaddown(final String path, String url) {
Retrofit retrofitLoaddown = new Retrofit.Builder()
.baseUrl("http://imtt.dd.qq.com/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
ApiService request = retrofitLoaddown.create(ApiService.class);
Observable<ResponseBody> observable = request.testDownload(url);//当你填进去的url是完整url的时候,设置的baseurl是无效的
observable.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new Observer<ResponseBody>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(ResponseBody responseBody) {
Log.i("gao", "测试 线程名字 = " + Thread.currentThread().getName());
//将Response写入到从磁盘中,详见下面分析 注意,这个方法是运行在子线程中的
writeResponseToDisk(path, responseBody);
}
@Override
public void onError(Throwable e) {
Log.i("gao", "testLoaddown 网络错误~ " + " 线程名字 = " + Thread.currentThread().getName());
Toast.makeText(MainActivity.this, "testLoaddown 网络错误~ ", Toast.LENGTH_SHORT).show();
}
@Override
public void onComplete() {
}
});
}
private void writeResponseToDisk(String path, ResponseBody responseBody) {
//从response获取输入流以及总大小
writeFileFromIS(new File(path), responseBody.byteStream(), responseBody.contentLength());
}
private static int sBufferSize = 8192;
//将输入流写入文件
private void writeFileFromIS(File file, InputStream is, long totalLength) {
//创建文件
if (!file.exists()) {
if (!file.getParentFile().exists())
file.getParentFile().mkdir();
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
Log.i("gao", "创建文件错误~ " + " 线程名字 = " + Thread.currentThread().getName());
}
}
OutputStream os = null;
long currentLength = 0;
try {
os = new BufferedOutputStream(new FileOutputStream(file));
byte data[] = new byte[sBufferSize];
int len;
while ((len = is.read(data, 0, sBufferSize)) != -1) {
os.write(data, 0, len);
currentLength += len;
//计算当前下载进度
Log.i("gao", "下载 进度 = " + (int) (100 * currentLength / totalLength));
}
//下载完成,并返回保存的文件路径
Log.i("gao", "下载完成 file.getAbsolutePath() = " + file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
Log.i("gao", "下载失败");
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
有什么不明白的可以看我上篇文章,Retrofit的简单实用(get post 下载文件),里面详细的介绍了怎么使用Rrtrofit。
文章用到的代码可以去这里下载 资源。欢迎大家评论,沟通。