这周末又败家买了鱼缸和一套设备,本来预备端午出去玩玩的目测只能在家吃土,周五把之前的X项目从X的实现迁移到了RxJava(RxAndroid),这一篇也就写一下相关的知识
强行安利(日更):https://github.com/ddwhan0123/Useful-Open-Source-Android
dependencies{ compile 'io.reactivex:rxjava:1.1.5' compile 'io.reactivex:rxandroid:1.2.0' }
总共写了两个小例子,先看第一个
看下运行效果:
看下日志:
这个干了什么呢?我们有一个按钮点击之后 随机切换 image,当然图片就都是 异步下载的。
看下代码(先解释大致逻辑和第一部分,方法名命名请无视,哈哈哈)
public class TwoActivity extends AppCompatActivity implements View.OnClickListener {
private Button testMap;
private ImageView tiffanyImg;
private RandomTools randomTools;
private ArrayList<SampleModel> data;
private TextView tiffanyText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);
StatusBarCompat.compat(this, getResources().getColor(R.color.status_bar_color));
StatusBarCompat.compat(this);
findId();
init();
setListener();
LogUtils.d("--->Main Thread id " + Thread.currentThread().getId());
}
private void findId() {
testMap = (Button) findViewById(R.id.testMap);
tiffanyImg = (ImageView) findViewById(R.id.tiffanyImg);
tiffanyText = (TextView) findViewById(R.id.tiffanyText);
}
private void init() {
randomTools = RandomTools.getInstance();
//填充数据
makeSampleModelData();
}
private void setListener() {
testMap.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.testMap:
setPhotoForOne(data);
// setPhotoForTwo(data);
break;
}
}
private void setPhotoForOne(ArrayList<SampleModel> data) {
Observable.just(data)
.subscribeOn(Schedulers.newThread())
.map(new Func1<ArrayList<SampleModel>, SampleModel>() {
@Override
public SampleModel call(ArrayList<SampleModel> list) {
LogUtils.d("第一个call线程id " + Thread.currentThread().getId());
//模拟返回集合的某个元素
int randInt = randomTools.getRandom(4);
return list.get(randInt);
}
}).map(new Func1<SampleModel, String>() {
@Override
public String call(SampleModel sampleModel) {
LogUtils.d("第二个call线程id " + Thread.currentThread().getId());
return sampleModel.getContent();
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override
public void call(String url) {
LogUtils.d("第三个call线程id " + Thread.currentThread().getId());
LogUtils.d("--->开始加载 " + url);
Glide.with(TwoActivity.this).load(url).into(tiffanyImg);
}
});
}
private void setPhotoForTwo(ArrayList<SampleModel> data) {
Observable.just(data).subscribeOn(Schedulers.newThread())
.flatMap(new Func1<ArrayList<SampleModel>, Observable<SampleModel>>() {
@Override
public Observable<SampleModel> call(ArrayList<SampleModel> sampleModels) {
return Observable.from(sampleModels);
}
}).filter(new Func1<SampleModel, Boolean>() {
@Override
public Boolean call(SampleModel sampleModel) {
return !sampleModel.getName().equals("");
}
}).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<SampleModel>() {
@Override
public void onCompleted() {
LogUtils.d("--->onCompleted");
}
@Override
public void onError(Throwable e) {
LogUtils.e(e);
}
@Override
public void onNext(SampleModel sampleModel) {
LogUtils.d("--->onNext");
Glide.with(TwoActivity.this).load(sampleModel.getContent()).into(tiffanyImg);
tiffanyText.setText(sampleModel.getName());
}
});
}
//制造数据源
private void makeSampleModelData() {
data = new ArrayList<>();
data.add(new SampleModel("Tiffany one", "http://hiphotos.baidu.com/zhixin/abpic/item/4651a712c8fcc3cea97dbce49045d688d53f206c.jpg"));
data.add(new SampleModel("Tiffany two", "http://pic.5442.com/2014/0930/06/5442.jpg"));
data.add(new SampleModel("", "http://img5q.duitang.com/uploads/item/201410/22/20141022214043_5EEKH.thumb.224_0.jpeg"));
data.add(new SampleModel("Tiffany four", "http://img5.duitang.com/uploads/item/201512/08/20151208163159_HGEM2.thumb.224_0.png"));
data.add(new SampleModel("Tiffany five", "http://img4.duitang.com/uploads/item/201510/29/20151029224537_ijEKF.thumb.224_0.jpeg"));
}
}
首先,我们在初始化的时候打了个Thread,然后再接下来的操作力再分别打出Thread,很明显除了加载操作,别的逻辑都让他在子线程里操作,为什么?最后说,先看下去!
这一部分主要实现在于setPhotoForOne这个方法
我们给被观察者传入一个ArrayList<SampleModel>
对象,然后让他在新线程里做数据整合的一些行为.subscribeOn(Schedulers.newThread())
,接着调用了 .map方法,在这里的Func1我传入了一个键值对。
第一个参数为传入的参数 参数类型也就是ArrayList<SampleModel>
第二个为返回的参数类型 为SampleModel
这极大的简便了我们的操作,不再是传统的传什么返回什么,让我们的代码有更好的拓展性,事件可以分的更清楚(L表达式情况下,传统的回调地狱还是蛮烦的,但是有好有坏,一个可读性好,一个代码少)
并且可以多次调用来满足我们的业务需求,像这样
.map(new Func1<SampleModel, String>() {
@Override
public String call(SampleModel sampleModel) {
LogUtils.d("第二个call线程id " + Thread.currentThread().getId());
return sampleModel.getContent();
}
})
当然我们的UI操作,还是要回到主线程来做,不然会有异常,但是这么做的一个好处是我们的复杂操作(异步,数据库,IO等都利用多CPU的优势来降低主线程的压力) 可以达到尽量避免卡UI的情况,重要的事情说三次 避免卡UI 避免卡UI 避免卡UI
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override
public void call(String url) {
LogUtils.d("第三个call线程id " + Thread.currentThread().getId());
LogUtils.d("--->开始加载 " + url);
Glide.with(TwoActivity.this).load(url).into(tiffanyImg);
}
});
然后再来提提另外2个方法 filter() 和 flatMap()
.flatMap(new Func1<ArrayList<SampleModel>, Observable<SampleModel>>() {
@Override
public Observable<SampleModel> call(ArrayList<SampleModel> sampleModels) {
return Observable.from(sampleModels);
}
})
这里的Func1也是传入2个参数
第一个为传入的类型,第二个是返回的Observable对象
和map一样他们都可以改变类型,但是只是返回的类型不同而已,大家可以根据自己的需求来选择不同的方法。
那返回的Observable又能干吗呢?
我们可以对他进行再次的嵌套,诸如二次just,二次from等等,有很大的拓展性
接下来再来提一下 .filter()
他可以为我们做“筛选”操作,
.filter(new Func1<SampleModel, Boolean>() {
@Override
public Boolean call(SampleModel sampleModel) {
return !sampleModel.getName().equals("");
}
})
false就会被过滤掉,也就是不会被观察者所执行
看下Log就清楚了
我们name为”“的那条数据就没有走onNext方法。
Ok,为什么用RxJava
1 不用再去麻烦的扣Handler做逻辑判断
2 更好的线程处理,方便好用
3 强大的API
源码地址:https://github.com/ddwhan0123/RxAndroidDemo
有问题可以WeChat我(活人,非公众号)
友情链接:http://gank.io/post/560e15be2dca930e00da1083#toc_1