RxJava详解
Retrofit 2.0 的使用
RxJava的使用(一)基本用法
RxJava + Retrofit完成网络请求
先看一个Demo:
private void Demo1() {
String[] a = {"" + R.mipmap.ic_launcher};
String[][] folders = {a, a};
Log.i(TAG, "thread0: " + Thread.currentThread().getId());
Observable
.from(folders)
.flatMap(new Func1<String[], Observable<String>>() {//String[]转换成String
@Override
public Observable<String> call(String[] file) {
Log.i(TAG, "flatMap: " + Thread.currentThread().getId());
return Observable.from(file);
}
})
.filter(new Func1<String, Boolean>() {
@Override
public Boolean call(String file) {
Log.i(TAG, "filter: " + Thread.currentThread().getId());
return file instanceof String;//false 过滤, true 不过滤
}
})
.map(new Func1<String, Integer>() {//String 转换成 Integer
@Override
public Integer call(String file) {
Log.i(TAG, "Func1: " + Thread.currentThread().getId());
return Integer.parseInt(file);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer bitmap) {
Log.i(TAG, "Action1-Next: " + Thread.currentThread().getId());
iv_img.setBackgroundResource(bitmap);
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
Log.i(TAG, "Action1-Error: " + Thread.currentThread().getId());
}
}, new Action0() {
@Override
public void call() {
Log.i(TAG, "Action1-Completed: " + Thread.currentThread().getId());
}
});
}
运行结果:
09-22 18:14:50.569 20855-20855/com.test.git.rxjavademo I/MainActivity-: thread0: 1
09-22 18:14:50.609 20855-31005/com.test.git.rxjavademo I/MainActivity-: flatMap: 22105
09-22 18:14:50.609 20855-31005/com.test.git.rxjavademo I/MainActivity-: filter: 22105
09-22 18:14:50.609 20855-31005/com.test.git.rxjavademo I/MainActivity-: Func1: 22105
09-22 18:14:50.609 20855-31005/com.test.git.rxjavademo I/MainActivity-: flatMap: 22105
09-22 18:14:50.609 20855-31005/com.test.git.rxjavademo I/MainActivity-: filter: 22105
09-22 18:14:50.609 20855-31005/com.test.git.rxjavademo I/MainActivity-: Func1: 22105
09-22 18:14:50.639 20855-20855/com.test.git.rxjavademo I/MainActivity-: Action1-Next: 1
09-22 18:14:50.649 20855-20855/com.test.git.rxjavademo I/MainActivity-: Action1-Next: 1
09-22 18:14:50.649 20855-20855/com.test.git.rxjavademo I/MainActivity-: Action1-Completed: 1
可以看出log输出与代码结构一致,所以RxJava的优点在于简洁,即使逻辑很复杂,线程切换也很方便。
RxJava:一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库。
build.gradle添加依赖:
compile 'io.reactivex:rxjava:1.2.0'
compile 'io.reactivex:rxandroid:1.2.1'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'com.jakewharton.rxbinding:rxbinding:0.4.0'
创建观察者
有两种方式
第一种:
Observer<String> observer = new Observer<String>() {
@Override
public void onCompleted() {
Log.i(TAG, "Observer-onCompleted: ");
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "Observer-onError: ");
}
@Override
public void onNext(String s) {
Log.i(TAG, "Observer-onNext: " + s);
}
};
第二种:
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onStart() {
super.onStart();
Log.i(TAG, "Subscriber-onStart: ");
}
@Override
public void onCompleted() {
Log.i(TAG, "Subscriber-onCompleted: ");
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "Subscriber-onError: ");
}
@Override
public void onNext(String s) {
Log.i(TAG, "Subscriber-onNext: ");
}
};
被观察者
有三种方式:
第一种:
Observable observable1 = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hello");
subscriber.onNext("Rx");
subscriber.onNext("Java");
subscriber.onNext("One");
subscriber.onCompleted();
}
});
第二种:
Observable observable2 = Observable.just("Hello", "Rx", "Java", "Two");
第三种:
String[] words = {"Hello", "Rx", "Java", "Three"};
Observable observable3 = Observable.from(words);
观察者与被观察者订阅
subscriber()做了三件事:
1.调用Subscriber.onStart()
2.调用Observable的OnSubscrible.call(Subscriber);
3.将传入的Subscriber作为Subscription返回,为了方便unsubscribe();
根据观察者创建方式不同订阅方式也不同:
方式一:
observable1.subscribe(observer);
方式二:
observable2.subscribe(subscriber);
Demo:
/**
* Observer Observable
*/
private void Demo2(){
/**
* 1.创建观察者Observer
*/
Observer<String> observer = new Observer<String>() {
@Override
public void onCompleted() {
Log.i(TAG, "Observer-onCompleted: ");
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "Observer-onError: ");
}
@Override
public void onNext(String s) {
Log.i(TAG, "Observer-onNext: " + s);
}
};
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onStart() {
super.onStart();
Log.i(TAG, "Subscriber-onStart: ");
}
@Override
public void onCompleted() {
Log.i(TAG, "Subscriber-onCompleted: ");
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "Subscriber-onError: ");
}
@Override
public void onNext(String s) {
Log.i(TAG, "Subscriber-onNext: ");
}
};
// subscriber.isUnsubscribed();//判断状态
// subscriber.unsubscribe();//取消订阅,尽量在onpause或onstop调用,防止内存泄漏
/**
* 2.创建被观察者Observable
*/
//type one
Observable observable1 = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hello");
subscriber.onNext("Rx");
subscriber.onNext("Java");
subscriber.onNext("One");
subscriber.onCompleted();
}
});
//type two
Observable observable2 = Observable.just("Hello", "Rx", "Java", "Two");
//type three
String[] words = {"Hello", "Rx", "Java", "Three"};
Observable observable3 = Observable.from(words);
/***
* 订阅Subscribe
*/
observable1.subscribe(observer);
observable2.subscribe(subscriber);
//subscriber()做了三件事:
//1.调用Subscriber.onStart()
//2.调用Observable的OnSubscrible.call(Subscriber);
//3.将传入的Subscriber作为Subscription返回,为了方便unsubscribe();
}
输出结果:
09-22 18:37:59.359 26737-26737/com.test.git.rxjavademo I/MainActivity-: Observer-onNext: Hello
09-22 18:37:59.359 26737-26737/com.test.git.rxjavademo I/MainActivity-: Observer-onNext: Rx
09-22 18:37:59.359 26737-26737/com.test.git.rxjavademo I/MainActivity-: Observer-onNext: Java
09-22 18:37:59.359 26737-26737/com.test.git.rxjavademo I/MainActivity-: Observer-onNext: One
09-22 18:37:59.369 26737-26737/com.test.git.rxjavademo I/MainActivity-: Observer-onCompleted:
09-22 18:37:59.369 26737-26737/com.test.git.rxjavademo I/MainActivity-: Demo2: ------------------------------------------------
09-22 18:37:59.369 26737-26737/com.test.git.rxjavademo I/MainActivity-: Subscriber-onStart:
09-22 18:37:59.369 26737-26737/com.test.git.rxjavademo I/MainActivity-: Subscriber-onNext: Hello
09-22 18:37:59.369 26737-26737/com.test.git.rxjavademo I/MainActivity-: Subscriber-onNext: Rx
09-22 18:37:59.369 26737-26737/com.test.git.rxjavademo I/MainActivity-: Subscriber-onNext: Java
09-22 18:37:59.369 26737-26737/com.test.git.rxjavademo I/MainActivity-: Subscriber-onNext: Two
09-22 18:37:59.369 26737-26737/com.test.git.rxjavademo I/MainActivity-: Subscriber-onCompleted:
Action0 Action1
Action0 无参
Action1 有参
Demo:
private void Demo3(){
/**
* Action1有参
* Action0无参
*/
Action1<String> onNextAction = new Action1<String>() {
@Override
public void call(String s) {
Log.i(TAG, "onNextAction-call: " + s);
}
};
Action1<Throwable> onErrorAction = new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
Log.i(TAG, "onErrorAction-call: ");
}
};
Action0 onCompletedAction = new Action0() {
@Override
public void call() {
Log.i(TAG, "onCompletedAction-call: ");
}
};
Observable observable = Observable.just("Hello", "Rx", "Java", "Two");
observable.subscribe(onNextAction);
observable.subscribe(onNextAction, onErrorAction);
observable.subscribe(onNextAction, onErrorAction, onCompletedAction);
}
输出结果:
09-22 18:41:36.709 4256-4256/? I/MainActivity-: onNextAction-call: Hello
09-22 18:41:36.709 4256-4256/? I/MainActivity-: onNextAction-call: Rx
09-22 18:41:36.709 4256-4256/? I/MainActivity-: onNextAction-call: Java
09-22 18:41:36.709 4256-4256/? I/MainActivity-: onNextAction-call: Two
09-22 18:41:36.709 4256-4256/? I/MainActivity-: Demo3: -----------------
09-22 18:41:36.709 4256-4256/? I/MainActivity-: onNextAction-call: Hello
09-22 18:41:36.709 4256-4256/? I/MainActivity-: onNextAction-call: Rx
09-22 18:41:36.709 4256-4256/? I/MainActivity-: onNextAction-call: Java
09-22 18:41:36.709 4256-4256/? I/MainActivity-: onNextAction-call: Two
09-22 18:41:36.709 4256-4256/? I/MainActivity-: Demo3: -----------------
09-22 18:41:36.709 4256-4256/? I/MainActivity-: onNextAction-call: Hello
09-22 18:41:36.709 4256-4256/? I/MainActivity-: onNextAction-call: Rx
09-22 18:41:36.709 4256-4256/? I/MainActivity-: onNextAction-call: Java
09-22 18:41:36.709 4256-4256/? I/MainActivity-: onNextAction-call: Two
09-22 18:41:36.709 4256-4256/? I/MainActivity-: onCompletedAction-call:
Schedulers和AndroidSchedulers 线程切换
- Schedulers.immediate(): 直接在当前线程运行,相当于不指定线程。这是默认的 Scheduler。
- Schedulers.newThread(): 总是启用新线程,并在新线程执行操作。
- Schedulers.io(): I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。
- Schedulers.computation(): 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。
- 另外, Android 还有一个专用的 AndroidSchedulers.mainThread(),它指定的操作将在 Android 主线程运行。
Demo:
private void Demo4(){
final int drawableRes = R.mipmap.ic_launcher;
Observable.create(new Observable.OnSubscribe<Drawable>() {
@Override
public void call(Subscriber<? super Drawable> subscriber) {
Log.i(TAG, "call: " + Thread.currentThread().getId());
Drawable drawable = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
drawable = getTheme().getDrawable(drawableRes);
}
subscriber.onNext(drawable);
subscriber.onCompleted();
}
}).subscribeOn(Schedulers.io())//指定subscribe()发生在IO线程
.observeOn(AndroidSchedulers.mainThread())//指定Subscriber的回调发生在主线程
// .subscribe(new Action1<Drawable>() {
// @Override
// public void call(Drawable drawable) {
//
// }
// })
.subscribe(new Observer<Drawable>() {
@Override
public void onCompleted() {
Log.i(TAG, "onCompleted: ");
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onError: ");
}
@Override
public void onNext(Drawable drawable) {
Log.i(TAG, "onNext: " + Thread.currentThread().getId());
if(drawable == null){
iv_img.setImageResource(android.support.v7.appcompat.R.drawable.abc_list_focused_holo);
}else {
iv_img.setImageDrawable(drawable);
}
}
});
}
log:
09-22 18:45:43.249 4256-7931/com.test.git.rxjavademo I/MainActivity-: call: 22217
09-22 18:45:43.279 4256-4256/com.test.git.rxjavademo I/MainActivity-: onNext: 1
09-22 18:45:43.279 4256-4256/com.test.git.rxjavademo I/MainActivity-: onCompleted:
map
demo:
private void Demo5(){
String s = "1";
Observable.just(s)
.map(new Func1<String, Integer>() {//String 转换成 Integer
@Override
public Integer call(String ss) {
Log.i(TAG, "Func1-call: " + ss);
return Integer.parseInt(ss);
}
})
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer s) {
Log.i(TAG, "Action1-call: " + s);
}
});
}
log:
09-22 18:46:48.039 4256-4256/com.test.git.rxjavademo I/MainActivity-: Func1-call: 1
09-22 18:46:48.039 4256-4256/com.test.git.rxjavademo I/MainActivity-: Action1-call: 1
flatMap
Demo:
private void Demo6(){
List<Integer> nums = new ArrayList<>();
nums.add(1);
nums.add(2);
nums.add(3);
Map<String, List<Integer>> map = new HashMap<>();
map.put("a", nums);
List<Map<String, List<Integer>>> list = new ArrayList<>();
list.add(map);
list.add(map);
list.add(map);
Subscriber<Integer> subscriber = new Subscriber<Integer>() {
@Override
public void onCompleted() {
Log.i(TAG, "onCompleted: ");
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onError: " + e.getMessage());
}
@Override
public void onNext(Integer ls) {
Log.i(TAG, "onNext: " + ls);
}
};
Observable.from(list)
.flatMap(new Func1<Map<String, List<Integer>>, Observable<Integer>>() {
@Override
public Observable<Integer> call(Map<String, List<Integer>> ls) {
Log.i(TAG, "call: ");
List<Integer> a = ls.get("a");
return Observable.from(a);
}
})
.subscribe(subscriber);
}
log:
09-22 18:48:46.529 4256-4256/com.test.git.rxjavademo I/MainActivity-: call:
09-22 18:48:46.529 4256-4256/com.test.git.rxjavademo I/MainActivity-: onNext: 1
09-22 18:48:46.529 4256-4256/com.test.git.rxjavademo I/MainActivity-: onNext: 2
09-22 18:48:46.529 4256-4256/com.test.git.rxjavademo I/MainActivity-: onNext: 3
09-22 18:48:46.529 4256-4256/com.test.git.rxjavademo I/MainActivity-: call:
09-22 18:48:46.529 4256-4256/com.test.git.rxjavademo I/MainActivity-: onNext: 1
09-22 18:48:46.529 4256-4256/com.test.git.rxjavademo I/MainActivity-: onNext: 2
09-22 18:48:46.529 4256-4256/com.test.git.rxjavademo I/MainActivity-: onNext: 3
09-22 18:48:46.529 4256-4256/com.test.git.rxjavademo I/MainActivity-: call:
09-22 18:48:46.529 4256-4256/com.test.git.rxjavademo I/MainActivity-: onNext: 1
09-22 18:48:46.529 4256-4256/com.test.git.rxjavademo I/MainActivity-: onNext: 2
09-22 18:48:46.529 4256-4256/com.test.git.rxjavademo I/MainActivity-: onNext: 3
09-22 18:48:46.529 4256-4256/com.test.git.rxjavademo I/MainActivity-: onCompleted:
doOnSubscribe
Demo:
private void Demo7(){
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
Log.i(TAG, "OnSubscribe-call: " + Thread.currentThread().getId());
subscriber.onNext("test");
subscriber.onCompleted();
}
})
.subscribeOn(Schedulers.io())
.doOnSubscribe(new Action0() {
@Override
public void call() {
Log.i(TAG, "Action0-call: " + Thread.currentThread().getId());
iv_img.setImageResource(R.mipmap.ic_launcher);//需要在主线程
}
})
.subscribeOn(AndroidSchedulers.mainThread())//指定主线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.i(TAG, "Action1-call: " + s + " thread:" + Thread.currentThread().getId());
}
});
}
log:
09-22 18:50:27.729 4256-4256/com.test.git.rxjavademo I/MainActivity-: Action0-call: 1
09-22 18:50:27.749 4256-12182/com.test.git.rxjavademo I/MainActivity-: OnSubscribe-call: 22230
09-22 18:50:27.769 4256-4256/com.test.git.rxjavademo I/MainActivity-: Action1-call: test thread:1
Retrofit
private void Demo8(){
//1.创建Retrofit对象
//2.声明接口NewsService
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://www.baidu.com/")
.build();
//3.创建api请求
NewsService api = retrofit.create(NewsService.class);
//4.发请求
final Call<ResponseBody> call = api.getNewss("123");
//同步调用
new Thread(new Runnable() {
@Override
public void run() {
Response<ResponseBody> response = null;
try {
response = call.execute();
Log.i(TAG, "Demo8-ok1: " + response.headers());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
Log.i(TAG, "Demo8: ---------------------------------------------------");
//异步调用
// call.enqueue(new Callback<ResponseBody>() {
// @Override
// public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
// Log.i(TAG, "Demo8-ok2: " + response.headers());
// }
//
// @Override
// public void onFailure(Call<ResponseBody> call, Throwable t) {
// Log.i(TAG, "Demo8-Error: " + t.getMessage());
// }
// });
//取消请求
// call.cancel();
}
public interface NewsService{
/**
*
* @param newsId
* @return
*/
// @GET("News/{newsId}")
// Call<News> getNews(@Path("newsId") String newsId);
/**
*
* @param newsId
* @return
*/
@GET("News/{newsId}")
Call<ResponseBody> getNewss(@Path("newsId") String newsId);
@GET
Call<List<String>> getSubjectsList(
@Url String url,
@QueryMap Map<String, Object> map
);
}
RxJava + Retrofit
private void Demo9(){
//http://test.api.loookapp.cn/api/banner/list?type=0
//1.创建Retrofit对象
//2.声明接口NewsService
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl("https://www.baidu.com/")
.build();
//3.创建api请求
UserService api = retrofit.create(UserService.class);
api.getUser("123")
.subscribeOn(Schedulers.newThread())//请求线程在新的线程
.observeOn(AndroidSchedulers.mainThread())//结果在主线程
.subscribe(new Observer<BannerListResp>() {
@Override
public void onCompleted() {
Log.i(TAG, "onCompleted: ");
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onError: " + e.getMessage());
e.printStackTrace();
}
@Override
public void onNext(BannerListResp resp) {
Log.i(TAG, "onNext: " + resp.banners.size());
}
});
}
public interface UserService{
String USER_INFO = "sku";
@GET(USER_INFO)
Observable<BannerListResp> getUser(@Query("sku_id") String sku_id);
}
rxbinding
github地址:rxbinding
/**
* 防抖点击(500ms内重复点击只记一次点击)
*/
private void Demo10(){
RxView.clicks(iv_img)
.throttleFirst(500, TimeUnit.MILLISECONDS)
.subscribe(new Action1<Void>() {
@Override
public void call(Void aVoid) {
Log.i(TAG, "call: click");
}
});
}