Android开发学习之路--RxAndroid之简单原理
学习了RxAndroid,其实也就是RxJava了,但是还是不是非常清楚到底RxAndroid有什么用呢?为什么要使用RxAndroid呢?这篇文章讲得不错,RxJava的原理。但是这里还是把整个过程学习下,这里主要参考文章中的原理,再把这个过程实现了一遍,也算是一知半解了。
一般实现
首先来个简单的例子,选出一个班级里面,学生成绩最好的,然后保存这个学生的姓名,这里简单实现下Student的类。
package com.jared.emrxandroidstudy;
/**
* Created by jared on 16/3/13.
*/
public class Student implements Comparable<Student> {
String name;
int grade;
@Override
public int compareTo(Student student) {
return Integer.compare(grade, student.grade);
}
}
这里通过实现Comparable来实现排序,通过成绩grade。接着实现StuApi。
package com.jared.emrxandroidstudy;
import java.util.List;
/**
* Created by jared on 16/3/13.
*/
public interface StuApi {
List<Student> queryStudents(String query);
String store(Student student);
}
接着实现我们的业务逻辑StudentHelper。
package com.jared.emrxandroidstudy;
import java.util.Collections;
import java.util.List;
/**
* Created by jared on 16/3/13.
*/
public class StudentHelper {
StuApi stuApi;
public String saveTheBestStudent(String query) {
List<Student> students = stuApi.queryStudents(query);
Student best = findBest(students);
String saveName = stuApi.store(best);
return saveName;
}
private Student findBest(List<Student> students) {
return Collections.max(students);
}
}
这里实现了saveTheBestStudent的方法,查询student,获取学生的链表,然后找到grade最大的,然后保存该学生的名字,返回。
这里需要经过三个步骤,而且每个步骤都是按顺序来实现的,是阻塞的方式的。
如果查询student花了很长时间的话,那么程序不应该一直在这里,我们需要的是处理完了告诉我们,而不是一直等着,就拿Android的click事件,当我们按下了button,才会触发onClick回调函数。那么接下去我们来实现下吧。
异步实现
修改StuApi如下:
package com.jared.emrxandroidstudy;
import java.util.List;
/**
* Created by jared on 16/3/13.
*/
public interface StuApi {
interface StudentsCallback {
void onStudentsListGetOk(List<Student> students);
void onQueryFailed(Exception e);
}
interface StoreCallback {
void onStudentStored(String name);
void onStoreFailed(Exception e);
}
void queryStudents(String query, StudentsCallback studentsCallback);
void store(Student student, StoreCallback storeCallback);
}
这里实现了StudentsCallback回调函数接口,当queryStudent成功的时候会回调onStudentsListGetOk,当失败的时候会调用onQueryFailed。StoreCallback回调函数接口,当store成功的时候回调onStudentStored,当失败的时候回调onStoreFailed。
接着修改StudentHelper:
package com.jared.emrxandroidstudy;
import java.util.Collections;
import java.util.List;
/**
* Created by jared on 16/3/13.
*/
public class StudentHelper {
public interface BestStudentCallback {
void onBestStudentSaved(String name);
void onError(Exception e);
}
StuApi stuApi;
public void saveTheBestStudent(String query, BestStudentCallback bestStudentCallback) {
stuApi.queryStudents(query, new StuApi.StudentsCallback() {
@Override
public void onStudentsListGetOk(List<Student> students) {
Student best = findBest(students);
stuApi.store(best, new StuApi.StoreCallback() {
@Override
public void onStudentStored(String name) {
bestStudentCallback.onBestStudentSaved(name);
}
@Override
public void onStoreFailed(Exception e) {
bestStudentCallback.onError(e);
}
});
}
@Override
public void onQueryFailed(Exception e) {
bestStudentCallback.onError(e);
}
});
}
private Student findBest(List<Student> students) {
return Collections.max(students);
}
}
这里实现了BestStudentCallback回调函数接口,当query成功的时候调用store方法,接着当store成功后回调onStudentStored方法,当失败后回调onBestStudentSaved,当失败的时候调用onError。
回调嵌套着回调,而且错误传递也是问题,分不清哪个错误,代码也失去了最开始阻塞方式的那种简洁优雅。
泛型回调实现
实现泛型回调Callback:
package com.jared.emrxandroidstudy;
/**
* Created by jared on 16/3/12.
*/
public interface Callback<T> {
void onResult(T result);
void onError(Exception e);
}
这里实现泛型回调函数Callback,实现两个方法,成功onResult,失败onError,成功传入的参数是泛型的,失败统一的Exception。接着添加StuApiWrapper,实现如下:
package com.jared.emrxandroidstudy;
import java.util.List;
/**
* Created by jared on 16/3/13.
*/
public class StuApiWrapper {
StuApi stuApi;
public void queryStudents(String query, Callback<List<Student>> listCallback) {
stuApi.queryStudents(query, new StuApi.StudentsCallback() {
@Override
public void onStudentsListGetOk(List<Student> students) {
listCallback.onResult(students);
}
@Override
public void onQueryFailed(Exception e) {
listCallback.onError(e);
}
});
}
public void store(Student student, Callback<String> callback) {
stuApi.store(student, new StuApi.StoreCallback() {
@Override
public void onStudentStored(String name) {
callback.onResult(name);
}
@Override
public void onStoreFailed(Exception e) {
callback.onError(e);
}
});
}
}
实现queryStudents和store两个方法,接着修改StudentHelper如下:
package com.jared.emrxandroidstudy;
import java.util.Collections;
import java.util.List;
/**
* Created by jared on 16/3/13.
*/
public class StudentHelper {
StuApiWrapper stuApiWrapper;
public void saveTheBestStudent(String query, Callback<String> bestStuCallback) {
stuApiWrapper.queryStudents(query, new Callback<List<Student>>() {
@Override
public void onResult(List<Student> result) {
Student student = findBest(result);
stuApiWrapper.store(student, bestStuCallback);
}
@Override
public void onError(Exception e) {
bestStuCallback.onError(e);
}
});
}
private Student findBest(List<Student> students) {
return Collections.max(students);
}
}
AsyncJob实现
这里saveTheBestStudent传入一个回调,当queryStudents成功后,会回调stuApiWrapper.store,然后成功的话,会在传入的bestStuCallback回调onStudentStored。
显然这样还是没有达到简洁明了,还需要传递回调函数,还是觉得麻烦,这里引入AsyncJob。
package com.jared.emrxandroidstudy;
/**
* Created by jared on 16/3/12.
*/
public abstract class AsyncJob<T> {
public abstract void start(Callback<T> callback);
}
如果在异步操作中返回一些临时对象,我们需要定义一个类出来。这样的一个对象需要包括常见的行为(以回调为单一参数)。
修改StuApiWrapper如下:
package com.jared.emrxandroidstudy;
import java.util.List;
/**
* Created by jared on 16/3/13.
*/
public class StuApiWrapper {
StuApi stuApi;
public AsyncJob<List<Student>> queryStudents(String query) {
return new AsyncJob<List<Student>>() {
@Override
public void start(Callback<List<Student>> callback) {
stuApi.queryStudents(query, new StuApi.StudentsCallback() {
@Override
public void onStudentsListGetOk(List<Student> students) {
callback.onResult(students);
}
@Override
public void onQueryFailed(Exception e) {
callback.onError(e);
}
});
}
};
}
public AsyncJob<String> store(Student student) {
return new AsyncJob<String>() {
@Override
public void start(Callback<String> callback) {
stuApi.store(student, new StuApi.StoreCallback() {
@Override
public void onStudentStored(String name) {
callback.onResult(name);
}
@Override
public void onStoreFailed(Exception e) {
callback.onError(e);
}
});
}
};
}
}
这里泛型抽象类AsyncJob实现了queryStudents和store,返回的数据都是AsyncJob。接着看看StudentHelper怎么来实现:
package com.jared.emrxandroidstudy;
import java.util.Collections;
import java.util.List;
/**
* Created by jared on 16/3/13.
*/
public class StudentHelper {
StuApiWrapper stuApiWrapper;
public AsyncJob<String> saveTheBestStudent(String query) {
return new AsyncJob<String>() {
@Override
public void start(Callback<String> bestStudentcallback) {
stuApiWrapper.queryStudents(query)
.start(new Callback<List<Student>>() {
@Override
public void onResult(List<Student> result) {
Student best = findBest(result);
stuApiWrapper.store(best)
.start(new Callback<String>() {
@Override
public void onResult(String result) {
bestStudentcallback.onResult(result);
}
@Override
public void onError(Exception e) {
bestStudentcallback.onError(e);
}
});
}
@Override
public void onError(Exception e) {
bestStudentcallback.onError(e);
}
});
}
};
}
private Student findBest(List<Student> students) {
return Collections.max(students);
}
}
这里在成功query后回调中找到最好成绩的学生,再存储。失败就调用onError了。这里省去了saveTheBestStudent的callback参数,回调都在AsyncJob的start方法里去实现,传递。
接着我们可以使用 AsyncJob把我们的方法分解成更小的操作。
package com.jared.emrxandroidstudy;
import java.util.Collections;
import java.util.List;
/**
* Created by jared on 16/3/13.
*/
public class StudentHelper {
StuApiWrapper stuApiWrapper;
public AsyncJob<String> saveTheBestStudent(String query) {
AsyncJob<List<Student>> studentsAsyncJob = stuApiWrapper.queryStudents(query);
AsyncJob<Student> bestStudentAsyncJob = new AsyncJob<Student>() {
@Override
public void start(Callback<Student> callback) {
studentsAsyncJob.start(new Callback<List<Student>>() {
@Override
public void onResult(List<Student> result) {
callback.onResult(findBest(result));
}
@Override
public void onError(Exception e) {
callback.onError(e);
}
});
}
};
AsyncJob<String> storeNameAsyncJob = new AsyncJob<String>() {
@Override
public void start(Callback<String> callback) {
bestStudentAsyncJob.start(new Callback<Student>() {
@Override
public void onResult(Student result) {
stuApiWrapper.store(result)
.start(new Callback<String>() {
@Override
public void onResult(String result) {
callback.onResult(result);
}
@Override
public void onError(Exception e) {
callback.onError(e);
}
});
}
@Override
public void onError(Exception e) {
callback.onError(e);
}
});
}
};
return storeNameAsyncJob;
}
private Student findBest(List<Student> students) {
return Collections.max(students);
}
}
这里使用了AsyncJob来转换我们所要的结果,接着我们实现一个转换方法:
package com.jared.emrxandroidstudy;
/**
* Created by jared on 16/3/12.
*/
public interface Func<T, R> {
R call(T t);
}
接口有两个类型成员,T对应于参数类型而R对应于返回类型。
接着修改AsyncJob:
package com.jared.emrxandroidstudy;
/**
* Created by jared on 16/3/12.
*/
public abstract class AsyncJob<T> {
public abstract void start(Callback<T> callback);
public <R> AsyncJob<R> map(Func<T, R> func) {
final AsyncJob<T> source = this;
return new AsyncJob<R>() {
@Override
public void start(Callback<R> callback) {
source.start(new Callback<T>() {
@Override
public void onResult(T result) {
R mapped = func.call(result);
callback.onResult(mapped);
}
@Override
public void onError(Exception e) {
callback.onError(e);
}
});
}
};
}
public <R> AsyncJob<R> flatMap(Func<T, AsyncJob<R>> func) {
final AsyncJob<T> source = this;
return new AsyncJob<R>() {
@Override
public void start(Callback<R> callback) {
source.start(new Callback<T>() {
@Override
public void onResult(T result) {
AsyncJob<R> mapped = func.call(result);
mapped.start(new Callback<R>() {
@Override
public void onResult(R result) {
callback.onResult(result);
}
@Override
public void onError(Exception e) {
callback.onError(e);
}
});
}
@Override
public void onError(Exception e) {
callback.onError(e);
}
});
}
};
}
}
这里实现了map和flatMap两个方法,接着修改StudentHelper如下:
package com.jared.emrxandroidstudy;
import java.util.Collections;
import java.util.List;
/**
* Created by jared on 16/3/13.
*/
public class StudentHelper {
StuApiWrapper stuApiWrapper;
public AsyncJob<String> saveTheBestStudent(String query) {
AsyncJob<List<Student>> bestListAsyncJob = stuApiWrapper.queryStudents(query);
AsyncJob<Student> bestStudentAsyncJob = bestListAsyncJob.map(new Func<List<Student>, Student>() {
@Override
public Student call(List<Student> students) {
return findBest(students);
}
});
AsyncJob<String> storeNameAsyncJob = bestStudentAsyncJob.flatMap(new Func<Student, AsyncJob<String>>() {
@Override
public AsyncJob<String> call(Student students) {
return stuApiWrapper.store(students);
}
});
return storeNameAsyncJob;
}
private Student findBest(List<Student> students) {
return Collections.max(students);
}
}
lambda实现
其实代码已经很简单了,接着我们通过lambda方式实现如下:
package com.jared.emrxandroidstudy;
import java.util.Collections;
import java.util.List;
/**
* Created by jared on 16/3/13.
*/
public class StudentHelper {
StuApiWrapper stuApiWrapper;
public AsyncJob<String> saveTheBestStudent(String query) {
AsyncJob<List<Student>> bestListAsyncJob = stuApiWrapper.queryStudents(query);
AsyncJob<Student> bestStudentAsyncJob = bestListAsyncJob.map(students -> findBest(students));
AsyncJob<String> storeNameAsyncJob = bestStudentAsyncJob.flatMap(student -> stuApiWrapper.store(student));
return storeNameAsyncJob;
}
private Student findBest(List<Student> students) {
return Collections.max(students);
}
}
RxJava实现
其实这些都可以使用RxJava来实现,修改StuApiWrapper:
package com.jared.emrxandroidstudy;
import java.util.List;
import rx.Observable;
import rx.Subscriber;
/**
* Created by jared on 16/3/13.
*/
public class StuApiWrapper {
StuApi stuApi;
public Observable<List<Student>> queryStudents(String query) {
return Observable.create(new Observable.OnSubscribe<List<Student>>() {
@Override
public void call(Subscriber<? super List<Student>> subscriber) {
stuApi.queryStudents(query, new StuApi.StudentsCallback() {
@Override
public void onStudentsListGetOk(List<Student> students) {
subscriber.onNext(students);
}
@Override
public void onQueryFailed(Exception e) {
subscriber.onError(e);
}
});
}
});
}
public Observable<String> store(final Student student) {
return Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
stuApi.store(student, new StuApi.StoreCallback() {
@Override
public void onStudentStored(String name) {
subscriber.onNext(name);
}
@Override
public void onStoreFailed(Exception e) {
subscriber.onError(e);
}
});
}
});
}
}
修改StudentHelper:
package com.jared.emrxandroidstudy;
import java.util.Collections;
import java.util.List;
import rx.Observable;
/**
* Created by jared on 16/3/13.
*/
public class StudentHelper {
StuApiWrapper stuApiWrapper;
public Observable<String> saveTheBestStudent(String query) {
Observable<List<Student>> bestListObservable = stuApiWrapper.queryStudents(query);
Observable<Student> bestStudentObservable = bestListObservable.map(students -> findBest(students));
Observable<String> storeNameObservable = bestStudentObservable.flatMap(student -> stuApiWrapper.store(student));
return storeNameObservable;
}
private Student findBest(List<Student> students) {
return Collections.max(students);
}
}
我们看到,通过简单的转化我们可以把异步操作给抽象出来。这个抽象出来的东西可以被用来操作和组合异步操作就像简单的方法那样。通过这种方法我们可以摆脱嵌套的回调,在处理异步结果时也能手动处理错误的传递。
Android开发学习之路--RxAndroid之简单原理的更多相关文章
- Android开发学习之路--RxAndroid之lambda
RxJava的简单使用基本上也了解了,其实还有一个比较好玩的就是java8才有的lambda了. lambda在android studio下的环境搭建 下载java8 下面就来搭建下这个环境 ...
- Android开发学习之路--UI之简单聊天界面
学了很多的ui的知识,这里就来实现个聊天的界面,首先来实现个layout的xml,代码如下: <?xml version="1.0" encoding="utf-8 ...
- Android开发学习之路--RxAndroid之操作符
学习了RxAndroid的一些基本知识,上篇文章也试过了RxAndroid的map操作符,接着来学习更多的操作符的功能吧. 操作符就是为了解决对Observable对象的变换的问题,操作符用于 ...
- Android开发学习之路--RxAndroid之初体验
学了一段时间android,看了部分的项目代码,然后想想老是学基础也够枯燥乏味的,那么就来学习学习新东西吧,相信很多学java的都听说过RxJava,那么android下也有RxAndroid. Rx ...
- Android开发学习之路--MediaPlayer之简单音乐播放器初体验
很多时候我们都会用手机来播放音乐,播放视频,那么具体地要怎么实现呢,其实主要是MediaPlayer类来完成的.下面通过简单的例子来实现一首歌曲的播放吧.新建工程MediaPlayerStudy,这里 ...
- Android开发学习之路-RecyclerView滑动删除和拖动排序
Android开发学习之路-RecyclerView使用初探 Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析 Android开 ...
- Android开发学习之路--基于vitamio的视频播放器(二)
终于把该忙的事情都忙得差不多了,接下来又可以开始good good study,day day up了.在Android开发学习之路–基于vitamio的视频播放器(一)中,主要讲了播放器的界面的 ...
- Android开发学习之路--Android Studio cmake编译ffmpeg
最新的android studio2.2引入了cmake可以很好地实现ndk的编写.这里使用最新的方式,对于以前的android下的ndk编译什么的可以参考之前的文章:Android开发学习之路– ...
- Android开发学习之路--网络编程之xml、json
一般网络数据通过http来get,post,那么其中的数据不可能杂乱无章,比如我要post一段数据,肯定是要有一定的格式,协议的.常用的就是xml和json了.在此先要搭建个简单的服务器吧,首先呢下载 ...
随机推荐
- 【NOIP2016】天天爱跑步
题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 个结点 ...
- CAN通信要注意的问题
CAN通信要注意的问题主要有: 1.参数配置 在初始化.启动.发送.接收 CAN信息时都要对CAN卡进行参数配置: (1)CAN卡的选择,我用到的是周立功的PCIE-9221,也就是DevType设备 ...
- springboot集成redis(mybatis、分布式session)
安装Redis请参考:<CentOS快速安装Redis> 一.springboot集成redis并实现DB与缓存同步 1.添加redis及数据库相关依赖(pom.xml) <depe ...
- 使用Unity NGUI-InputField组件输入时发现显示为白色就是看不到字体
今天在接入android支付宝 SDK时,打包运行时,发现使用Unity NGUI-InputField组件输入时发现显示为白色就是看不到字体,查找一下发现是与android交互存在的问题, 只需在A ...
- Tomcat访问路径去掉发布项目的项目名称
需求: 把发布到Tomcat下的web项目,访问路径去掉项目名称 实现方式及原理: 方式一: 原理:Tomcat的默认根目录是ROOT,实际上ROOT这个项目在实际生产环境是没有用的,所以我们可以用我 ...
- java总结之基础类型与常量池
1.基础类型有byte short int long char boolean float double八种. 其中byte short int long char 的包装类型是存放在常量池(用来维护 ...
- tf.nn.conv2d 和 tf.nn.max_pool 中 padding 分别为 'VALID' 和 'SAME' 的直觉上的经验和测试代码
这个地方一开始是迷糊的,写代码做比较分析,总结出直觉上的经验. 某人若想看精准的解释,移步这个网址(http://blog.csdn.net/fireflychh/article/details/73 ...
- vue+node.js+webpack开发微信公众号功能填坑——v -for循环
页面整体框架实现,实现小功能,循环出数据,整体代码是上一篇 vue+node.js+webpack开发微信公众号功能填坑--组件按需引入 修改部门代码 app.vue <yd-flexbox&g ...
- Python中strip()、lstrip()、rstrip()用法详解
Python中有三个去除头尾字符.空白符的函数,它们依次为: strip: 用来去除头尾字符.空白符(包括\n.\r.\t.' ',即:换行.回车.制表符.空格)lstrip:用来去除开头字符.空白符 ...
- Kafka生产者-向Kafka中写入数据
(1)生产者概览 (1)不同的应用场景对消息有不同的需求,即是否允许消息丢失.重复.延迟以及吞吐量的要求.不同场景对Kafka生产者的API使用和配置会有直接的影响. 例子1:信用卡事务处理系统,不允 ...