使用rxjava在Dialog中处理异步任务,处理完毕更新界面
开发环境:Android studio
build.gradle中添加
dependencies {
compile 'io.reactivex:rxjava:1.1.3'
compile 'io.reactivex:rxandroid:1.1.0'
}
添加一个类管理被订阅者和订阅者的生命周期RxManager.java:
package com.example.acer.util;
import java.util.HashMap;
import java.util.Map;
import rx.Subscription;
import rx.subscriptions.CompositeSubscription;
/**
* 管理订阅的生命周期
*/
public class RxManager {
private CompositeSubscription mSubscriptions = null;
private Map mMap = null;
public void add(Subscription m) {
if (mSubscriptions == null) {
mSubscriptions = new CompositeSubscription();
}
mSubscriptions.add(m);
}
public void remove(Subscription m) {
if (mSubscriptions == null) return;
mSubscriptions.remove(m);
}
public void clear() {
if (mSubscriptions != null) {
mSubscriptions.unsubscribe();// 取消订阅
mSubscriptions = null;
}
if (mMap != null) {
mMap.clear();
mMap = null;
}
}
public void add(String eventType, Subscription sub) {
if (mMap == null) {
mMap = new HashMap<>();
}
remove(mMap.put(eventType, sub));
add(sub);
}
public void remove(String eventType) {
if (mMap == null) return;
remove(mMap.remove(eventType));
}
}
用于测试的数据结构:
class StuHandUpBO{
public StuHandUpBO(String nam, int i)
{
name = nam;
id = i;
}
public String name = "";
public int id = 0;
public int getOrder()
{
return id;
}
}
对话框中添加一个管理者的实例:
protected RxManager mRx;
在对话框的onCreate时生成实例:
mRx = new RxManager();
在对话框的生命结束时释放所有的订阅:
protected void onDestroy(){
mRx.clear();
}
对话框中添加方法,添加匿名的订阅者:
public void add(Subscription sub) {
mRx.add(sub);
}
对话框中添加方法,添加指定名称的订阅者:(建议使用这个,这样添加同名的时候,可以自动将之前的那个释放掉)
public void add(String eventType, Subscription sub) {
mRx.add(eventType, sub);
}
对话框中再添加一些方法:
//模拟后台异步任务
public String getAsString(String url) throws Exception {
int i=0;
while (i<100)
{
i++;
Thread.sleep(50);
}
return "{\"name\":\"zhangsan\",\"id\":\"666666\"}";
}
//把任务封装为,可被订阅对象
public Observable getAsObservableString(final String url) {
return Observable.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber super String> subscriber) {
try {
subscriber.onNext(getAsString(url));
subscriber.onCompleted();
} catch (Exception e) {
subscriber.onError(e);
}
}
});
}
//对第一个封装的被订阅者再封装一次,形成一个新的被订阅者,因为第一次的结果的形式不是需要的,还要加工
public Observable> getObservable() {
return getAsObservableString("127.0.0.1")//测试假定的参数,模拟网络操作
.map(new Func1>() {
@Override
public List call(String result) {
return proCessResult(result);
}
});
}
//对异步任务获取的结果进行二次加工的工作,因为假设任务返回的结果不是我们想要的形式,模拟这种情况
public ArrayList proCessResult(String jsonstr)
{
ArrayList list = new ArrayList<>();
list.add(new StuHandUpBO("zhangsan", 666));
return list;
}
//订阅者的工作需要在ui线程进行操作,实现转到ui的方法
final Observable.Transformer transFormerUi = new Observable.Transformer() {
@Override public Object call(Object observable) {
return ((Observable) observable)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread());
}
};
public Observable.Transformer toUIThread() {
return (Observable.Transformer) transFormerUi;
}
(实际项目中,如果这个耗时的异步工作是所有界面都可能需要去做的,我们可以将上面的一堆代码放到一个基类中,其它的界面类只要继承这个类就有了这个功能)
最后我们测试完成我们的工作,并更新界面:
//给本次的订阅事件起个名字
String MY_TASK_NAME = "my_task_name";
//测试对异步任务,添加订阅者
public void doTastAsync() {
add(MY_TASK_NAME, getObservable()
.compose(this.>toUIThread())
.subscribe(new Action1>() {
@Override
public void call(List userInfos) {
//工作完成了,在这里实现我们更新界面的代码
Toast.makeText(MainActivity.this, "userInfos.size:"+userInfos.size(), Toast.LENGTH_LONG).show();
}
}, new Action1() {
@Override
public void call(Throwable throwable) {
//工作出现了错误
Toast.makeText(MainActivity.this, throwable.toString(), Toast.LENGTH_LONG).show();
}
}));
}
我们只要调用doTastAsync()这个方法,就可以异步完成我们的工作,并在完成之后更新界面。