rxjava听了很多,因为一般都是自己做异步框架,所以没有用rxjava真正做过项目,顶多就写过一些demo。在写demo过程中,发现rxjava很麻烦,因此果断放弃了。最近有点空闲时间,想学习多一点框架的原理及应用,看了半天rxjava源码,虽然还不至于晕,但是还不是很理解为什么要那么做,刚好看到一篇博文,主要由简单代码模拟rxjava处理异步,发现我们平常写的callback还能这么写,在这里做一下记录。
先声明几个简单的类:
// 小车类
public class Car {
private String name;
public Car(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// 猫类
public class Cat {
private String name;
public Cat(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// 狗类
public class Dog {
private String name;
public Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// 魔术师类
public class MagicService2 {
public interface Callback <T> {
void onSuccess(T result);
void onError(Exception e);
}
// 把猫变成很多小车
void magicCat(Cat cat, Callback<List<Car>> callback) {
// 魔术师比较菜,变的过程中可能需要时间,这里模拟异步
try {
List<Car> carList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
carList.add(new Car(cat.getName() + i));
}
callback.onSuccess(carList);
} catch (Exception e) {
callback.onError(e);
}
}
// 把车变成狗
void magicCar(Car car, Callback<Dog> callback) {
// 魔术师比较菜,变的过程中可能需要时间,这里模拟异步
callback.onSuccess(new Dog(car.getName()));
}
}
然后调用魔术师的2个魔术方法:
final MagicService2 service2 = new MagicService2();
service2.magicCat(cat, new MagicService2.Callback<List<Car>>() {
@Override
public void onSuccess(List<Car> result) {
service2.magicCar(result.get(result.size() - 1), new MagicService2.Callback<Dog>() {
@Override
public void onSuccess(Dog result) {
Log.e(getClass().getName(), result.getName());
}
@Override
public void onError(Exception e) {
Log.e(getClass().getName(), e.getMessage());
}
});
}
@Override
public void onError(Exception e) {
Log.e(getClass().getName(), e.getMessage());
}
});
以上代码,相信很多人都这么写过,我之前就一直很反感这种多层异步代码,一直找不到方法改善。要是3层以上的异步,“迷之缩进”便会很明显,会影响我们阅读代码,必须改进。
由于魔术师的方法是无返回值的,所以只能在callback回调里面再写调用异步操作,这样就会造成“迷之缩进”。既然是因为无返回值造成的,我们不妨这么设计:
public class MagicService3 {
public interface Callback <T> {
void onSuccess(T result);
void onError(Exception e);
}
public abstract class AsyncJob <T> {
abstract void execute(Callback<T> callback);
}
AsyncJob<List<Car>> magicCat(final Cat cat) {
return new AsyncJob<List<Car>>() {
@Override
void execute(Callback<List<Car>> callback) {
try {
List<Car> carList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
carList.add(new Car(cat.getName() + i));
}
callback.onSuccess(carList);
} catch (Exception e) {
callback.onError(e);
}
}
};
}
AsyncJob<Dog> magicCar(final Car car) {
return new AsyncJob<Dog>() {
@Override
void execute(Callback<Dog> callback) {
callback.onSuccess(new Dog(car.getName()));
}
};
}
}
调用时是这样的:
final MagicService3 service3 = new MagicService3();
MagicService3.AsyncJob<List<Car>> job1 = service3.magicCat(cat);
job1.execute(new MagicService3.Callback<List<Car>>() {
@Override
public void onSuccess(List<Car> result) {
MagicService3.AsyncJob<Dog> job2 = service3.magicCar(result.get(result.size() - 1));
job2.execute(new MagicService3.Callback<Dog>() {
@Override
public void onSuccess(Dog result) {
Log.e(getClass().getName(), result.getName());
}
@Override
public void onError(Exception e) {
Log.e(getClass().getName(), e.getMessage());
}
});
}
@Override
public void onError(Exception e) {
Log.e(getClass().getName(), e.getMessage());
}
});
这样下去也会产生“迷之缩进”。脑洞大一点,如果job1可以转化为job2,那该多好呀,的确可以:
public class MagicService4 {
public interface Callback <T> {
void onSuccess(T result);
void onError(Exception e);
}
public interface Func <T, R> {
R fun(T data);
}
public abstract class AsyncJob <T> {
abstract void execute(Callback<T> callback);
public <R> AsyncJob<R> map(final Func<T, R> func) {
final AsyncJob<T> source = this;
return new AsyncJob<R>() {
@Override
void execute(final Callback<R> callback) {
source.execute(new Callback<T>() {
@Override
public void onSuccess(T result) {
R data = func.fun(result);
callback.onSuccess(data);
}
@Override
public void onError(Exception e) {
callback.onError(e);
}
});
}
};
}
public <R> AsyncJob<R> flapMap(final Func<T, AsyncJob<R>> func) {
final AsyncJob<T> source = this;
return new AsyncJob<R>() {
@Override
void execute(final Callback<R> callback) {
source.execute(new Callback<T>() {
@Override
public void onSuccess(T result) {
AsyncJob<R> data = func.fun(result);
data.execute(new Callback<R>() {
@Override
public void onSuccess(R result) {
callback.onSuccess(result);
}
@Override
public void onError(Exception e) {
callback.onError(e);
}
});
}
@Override
public void onError(Exception e) {
callback.onError(e);
}
});
}
};
}
}
AsyncJob<List<Car>> magicCat(final Cat cat) {
return new AsyncJob<List<Car>>() {
@Override
void execute(Callback<List<Car>> callback) {
try {
List<Car> carList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
carList.add(new Car(cat.getName() + i));
}
callback.onSuccess(carList);
} catch (Exception e) {
callback.onError(e);
}
}
};
}
AsyncJob<Dog> magicCar(final Car car) {
return new AsyncJob<Dog>() {
@Override
void execute(Callback<Dog> callback) {
callback.onSuccess(new Dog(car.getName()));
}
};
}
}
这下调用就简单了:
final MagicService4 service4 = new MagicService4();
MagicService4.AsyncJob<List<Car>> job3 = service4.magicCat(cat);
MagicService4.AsyncJob<Car> job4 = job3.map(new MagicService4.Func<List<Car>, Car>() {
@Override
public Car fun(List<Car> data) {
return data.get(data.size() - 1);
}
});
MagicService4.AsyncJob<Dog> job5 = job4.flapMap(new MagicService4.Func<Car, MagicService4.AsyncJob<Dog>>() {
@Override
public MagicService4.AsyncJob<Dog> fun(Car data) {
return service4.magicCar(data);
}
});
job5.execute(new MagicService4.Callback<Dog>() {
@Override
public void onSuccess(Dog result) {
Log.e(getClass().getName(), result.getName());
}
@Override
public void onError(Exception e) {
Log.e(getClass().getName(), e.getMessage());
}
});
这样,“迷之缩进”便解决了。这种组合思想实在太赞了,又学到东西了!!!
参考资料
NotRxJava懒人专用指南