前言
前面写RxJava的时候就提过要来这么一篇RxJava和Retrofit结合使用的博客,那时由于Retrofit那篇博客还没写,直接写两个结合的用法的话理解起来会比较困难。现在Retrofit我们也学完了,是时候把欠的的那篇博客不上了。两个组合起来用法其实还是挺简单的,说白了就是将Retrofit的网络请求接口方法的返回值由Callback修改为Observable,这样一来这两个框架就结合起来了,Retrofit网络请求的结果就可以通过RxJava各种操作符进行各种花式操作了。这篇博客还是老规矩直接上例子,在例子中解释说明。
Retrofit不使用RxJava时和使用时对比
- 用于描述网络请求的接口设置
public interface GetRequest_Interface {
// 传统方式:Call<..>接口形式
@GET("部分url地址")
Call getCall();
}
// RxJava 方式:Observable<..>接口形式
@GET("url地址")
public interface GetRequest_Interface {
Observable getCall();
- 网络请求的封装形式 & 发送形式
<--传统方式 -> >
// 1. 创建 网络请求接口 的实例
GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
// 2. 采用Call<..>接口 对 发送请求 进行封装
Call call = request.getCall();
// 3. 发送网络请求(异步)
call.enqueue(new Callback() {
// 请求成功时回调
@Override
public void onResponse(Call call, Response response) {
...
}
// 请求失败时回调
@Override
public void onFailure(Call call, Throwable throwable) {
....
}
});
<--RxJava 版方式 -> >
// 1. 创建 网络请求接口 的实例
GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
// 2. 采用Observable<...>形式 对 网络请求 进行封装
Observable observable = request.getCall();
// 3. 发送网络请求(异步)
observable.subscribeOn(Schedulers.io()) // 在IO线程进行网络请求
.observeOn(AndroidSchedulers.mainThread()) // 回到主线程 处理请求结果
.subscribe(new Observer() {
// 发送请求后调用该复写方法(无论请求成功与否)
@Override
public void onSubscribe(Disposable d) {
...// 初始化工作
}
// 发送请求成功后调用该复写方法
@Override
public void onNext(Translation result) {
...// 对返回结果Translation类对象 进行处理
}
// 发送请求成功后,先调用onNext()再调用该复写方法
@Override
public void onComplete() {
Log.d(TAG, "请求成功");
}
// 发送请求失败后调用该复写方法
@Override
public void onError(Throwable e) {
Log.d(TAG, "请求失败");
}
});
- 这样一对比是不是瞬间就明白了这两个框架结合起来的用法了,没错,就是这么简单,到此为止本篇博客就结束了,哈哈,骗你的,皮这一下很开心,说好的例子还没写呢,下面我们就以一个例子来讲解下具体用法。
两个框架结合使用的网络请求例子
1. build.gradle中添加两个库的依赖、Gson解析的依赖和图片加载库Glide的依赖
dependencies {
//添加RxJava依赖
implementation "io.reactivex.rxjava2:rxjava:2.2.3"
//添加RxAndroid依赖,专门用于Android的Rx库
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
//添加Retrofit依赖
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
//衔接 Retrofit & RxJava,此处一定要注意使用RxJava2的版本
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
//添加Gson解析
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
//添加图片加载库依赖
implementation 'com.github.bumptech.glide:glide:4.8.0'
}
2. 添加网络权限
3. 创建接收服务器返回数据的类
URL : https://www.zhuangbi.info/search?q=在下
- ZaiXiaImage.java
public class ZaiXiaImage {
//这里只取有用字段,其它没用字段就懒得写了
public String created_at;
public String image_url;
}
4. 创建用于描述网络请求的接口
import java.util.List;
import io.reactivex.Observable;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface ZaiXiaApi {
//采用 注解 + Observable<...>接口 描述网络请求参数
//search()是接收网络请求数据的方法,这里是从所有图片中将“在下”类别的图片查找出来
@GET("search")
Observable> search(@Query("q") String query);
}
5. 布局部分代码
- 布局由于用到了RecyclerView和CardView,所以别忘了添加依赖
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
- activity_main.xml
- 图片布局:grid_item.xml
6. 用于展示图片的适配器代码
- ZaiXiaGridAdapter.java
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import java.util.List;
public class ZaiXiaGridAdapter extends RecyclerView.Adapter {
private List images;
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_item, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
MyViewHolder myViewHolder = (MyViewHolder) holder;
ZaiXiaImage image = images.get(position);
Glide.with(holder.itemView.getContext()).load(image.image_url).into(myViewHolder.imageIv);
myViewHolder.descriptionTv.setText(image.created_at);
}
@Override
public int getItemCount() {
return images == null ? 0 : images.size();
}
public void setImages(List images) {
this.images = images;
notifyDataSetChanged();
}
private class MyViewHolder extends RecyclerView.ViewHolder {
ImageView imageIv; //图片
TextView descriptionTv; //创建时间
public MyViewHolder(View itemView) {
super(itemView);
imageIv = itemView.findViewById(R.id.imageIv);
descriptionTv = itemView.findViewById(R.id.descriptionTv);
}
}
}
7. 主页面代码
- MainActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
public class MainActivity extends AppCompatActivity {
private RecyclerView gridRv;
private ZaiXiaGridAdapter adapter;
//切断观察者操作对象
private Disposable disposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridRv = findViewById(R.id.gridRv);
gridRv.setLayoutManager(new GridLayoutManager(MainActivity.this, 2));
adapter = new ZaiXiaGridAdapter();
gridRv.setAdapter(adapter);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.zhuangbi.info/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) //支持RxJava
.build();
//创建网络请求接口的实例
ZaiXiaApi zaiXiaApi = retrofit.create(ZaiXiaApi.class);
//通过接口方法获取请求对象,用Observable<...>进行了封装,将返回用Observable对象
Observable> observable = zaiXiaApi.search("在下");
disposable = observable.subscribeOn(Schedulers.io())
.map(new Function, List>() { //通过map操作符将时间数据格式进行转换
@Override
public List apply(List zaiXiaImages) throws Exception {
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
List images = new ArrayList<>();
for (int i = 0; i < zaiXiaImages.size(); i++) {
ZaiXiaImage zaiXiaImage = zaiXiaImages.get(i);
Date date = inputFormat.parse(zaiXiaImage.created_at);
zaiXiaImage.created_at = outputFormat.format(date);
images.add(zaiXiaImage);
}
return images;
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer>() {
@Override
public void accept(@NonNull List images) throws Exception {
adapter.setImages(images);
}
}, new Consumer() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
Toast.makeText(MainActivity.this, "数据加载失败", Toast.LENGTH_SHORT).show();
}
});
}
@Override
protected void onDestroy() {
//页面销毁时切断观察者,不再接收上游事件
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
super.onDestroy();
}
}
8. 运行效果
感谢
Android:Retrofit 结合 RxJava的优雅使用(含实例教程)