使用 RxJava 和 Retrofit
一、RxJava 简介
RxJava
是Reactive Extensions
的JVM
实现:用于通过使用observable
序列来构建异步和基于事件的程序的库。官方描述:
RxJava is a Java VM implementation of Reactive Extensions: a library for composing asynchronous and event-based programs by using observable sequences.
It extends the observer pattern to support sequences of data/events and adds operators that allow you to compose sequences together declaratively while abstracting away concerns about things like low-level threading, synchronization, thread-safety and concurrent data structures.
- 参考
抛物线
的博客 给 Android 开发者的 RxJava 详解 。
二、RxJava 配合 Retrofit 使用
1.添加gradle
依赖
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
2.在 AndroidManifest.xml
里加入网络访问权限,创建 MovieEntity
实体类,解析服务器返回的 JSON 数据,建议使用 Gson 解析,使用 GsonFormat
或 GsonOrXmlFormat
插件一键生成
<uses-permission android:name="android.permission.INTERNET"/>
// MovieEntity 类的代码就不贴了
3.创建一个Java接口 ApiService
来作为HTTP请求接口,返回值是 Observable
public interface ApiService {
@GET("top250")
Observable<MovieEntity> getTopMovies(@Query("start") int start, @Query("count") int count);
}
4.实例化 Retrofit ,并通过 Retrofit 对象实现上面的接口,封装在 HttpMethod 类里面,并且实现接口的方法。
public class HttpMethods {
private static final String BASE_URL = "https://api.douban.com/v2/movie/";
private static final int TIME_OUT = 4;
private Retrofit retrofit;
private ApiService apiService;
/**
* 私有化构造函数
*/
private HttpMethods() {
OkHttpClient client = new OkHttpClient();
client.newBuilder().connectTimeout(TIME_OUT, TimeUnit.SECONDS);
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
apiService = retrofit.create(ApiService.class);
}
/**
* 创建单例
*/
private static class SingleInstance{
private static final HttpMethods INSTANCE = new HttpMethods();
}
/**
* 获取单例
* @return
*/
public static HttpMethods getInstance(){
return SingleInstance.INSTANCE;
}
/**
* get top movies
* @param start 起始位置
* @param count 获取数量
* @param observer 观察值对象
*/
public void getTopMovies(int start, int count, Observer<MovieEntity> observer) {
apiService.getTopMovies(start, count)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
}
5.MainActivity 里实现请求
public class MainActivity extends AppCompatActivity {
private final String TAG = String.valueOf(getCallingActivity());
//private static String BASE_URL = "https://api.douban.com/v2/movie/";
private Button getData;
private RecyclerView recyclerView;
private List<String> dataList = new ArrayList<>();
private int START = 0; // 起始页数
private int COUNT = 25; // 每次加载数量
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 设置 RecyclerView
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
// 设置 Button
getData = (Button) findViewById(R.id.get_data);
getData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getMovies();
}
});
}
private void getMovies() {
HttpMethods.getInstance().getTopMovies(START,COUNT, new Observer<MovieEntity>() {
@Override
public void onSubscribe(Disposable d) {
Log.e(TAG, "onSubscribe: " + d.toString());
}
/**
* 请求成功
* @param value 返回数据
*/
@Override
public void onNext(MovieEntity value) {
for (int i = 0; i < COUNT; i++) {
if (START < 250/COUNT){ // 判断是否加载完
String title = value.getSubjects().get(i).getTitle();
Log.e(TAG, "onNext: " + (i+(START-1)*COUNT+1) + title);
dataList.add(title);
} else {
dataList.add("没有更多了");
}
}
recyclerView.setAdapter(new MyAdapter(dataList));
}
/**
* 请求错误
* @param e 抛出异常
*/
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: " + e.getMessage());
}
/**
* 每次请求完成执行
*/
@Override
public void onComplete() {
Log.e(TAG, "onComplete: ");
}
});
START++; // 页数加一
}
}
- 附上:RecyclerView 的 Adapter 和 ViewHolder
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
private List<String> datas = null;
public MyAdapter(List<String> datas) {
this.datas = datas;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.title.setText(datas.get(position));
}
@Override
public int getItemCount() {
return datas.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public ViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
}
}
}
- 效果图:
参考:
tough1985: RxJava 与 Retrofit 结合的最佳实践