我刚刚开始学习RxJava,我已经阅读并观看了不少教程,但有些事情还没有点击。我已经深入了解并开始修改我的应用程序的一个API调用以返回一个Observable。目前,API调用由AsyncTaskLoader
使用,它从本地数据库返回缓存数据,然后进行调用,合并数据并再次返回。这个模式听起来像是我的RxJava实验的完美主题,但从小开始,我想从我的API调用中返回一个observable。
这是我原来的电话:
public static ArrayList<Stuff> getStuffForId(String id)
throws IOException, UserNotAuthenticatedException {
Profile profile = getProfile();
HashMap<String,ArrayList<Stuff>> map = profile.getStuff();
if (map == null) {
throw new IOException("error processing - map cannot be null");
}
return map.get(id);
}
private static Profile getProfile()
throws IOException, UserNotAuthenticatedException {
// <.. getting url, auth tokens and other stuff to prepare the Request ..>
Response response = sHttpClient.newCall(request).execute();
if (response.code() == ERR_AUTH_REJECTED) {
throw new UserNotAuthenticatedException(response.body().string());
}
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
Gson gson = new Gson();
String result = response.body().string();
response.body().close();
return gson.fromJson(result, Profile.class);
}
在RxJava世界中,我正在思考以下几点:
public static Observable<ArrayList<Stuff>> getStuffForId(String id) {
return getProfile().map(
Profile::getStuff).map(
map -> {
if (map == null) {
Observable.error(new IOException("error processing - map cannot be null"));
}
return map.get(id);
});
}
private static Observable<Profile> getProfile() {
return Observable.fromCallable(() -> {
// <.. getting url, auth tokens and other stuff to prepare the Request ..>
Response response = sHttpClient.newCall(request).execute();
if (response.code() == ERR_AUTH_REJECTED) {
throw new UserNotAuthenticatedException(response.body().string(),
authToken);
}
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
Gson gson = new Gson();
String result = response.body().string();
response.body().close();
return gson.fromJson(result, Profile.class);
});
}
这看起来像人们期望的那样吗?我仍然不确定fromCallable()
和defer()
之间的区别以及您使用哪一个。还不确定在fromCallable()
方法中抛出异常的位置 - 它们会自动结束我的订阅者的onError
还是我需要在我的getStuffForId
方法中处理它们?最后,Android Studio警告我return map.get(id)
可能会抛出nullPointer。这只是因为IDE不理解Observable.error
将终止执行,还是因为我不明白Observable.error
会发生什么?
答案 0 :(得分:2)
1)差异b / w fromCallable()
和defer()
?
Well defer()
在某些订阅者订阅之前不会创建Observable,并且每次用户订阅时都会创建新的Obervable。请参阅此link,了解您希望使用defer()
的原因。
2)在fromCallable()
方法中抛出异常的位置在哪里?
异常会在Observer中捕获,然后作为Throwable对象传递给Subscriber的onError()
方法。
3)Android Studio警告我return map.get(id)
可能会抛出nullPointer。
因为当它实际为null时,你不会在if语句中返回任何内容。代码将超出if语句,从而导致nullPointerException。 Observable.error());
返回一个Observable并且它不会抛出任何东西,为了做到这一点,你必须显式抛出RuntimeException。
4)这看起来与人们期望的一样。
除了上述错误之外,没有任何错误,但您可以在线搜索rxJava模式以便在结构上进行更好的编码。
答案 1 :(得分:1)
是的,但是请看一下图书馆,这些图书馆会为你做管道工作:https://github.com/square/retrofit 如果你在fromCallable中抛出任何异常,你将使用defer并返回Observable.error(new Exception(&#34; error&#34;))
这两种方法都是用于创建可观察对象的工厂。从callable要求你返回一个像字符串等的值。推迟像你一样返回一个可观察到的东西。如果你想包装一些返回某种类型的非observable-method-call,你可以使用fromCallable。此外,fromCallable将处理您的异常并将其传递给链。相反,如果您想处理自己的异常/可观察对象,则会使用延迟。您可以返回一个发出值的observable,然后完成或不完成。 &#39; fromCallable&#39;我们将完成一个值和onComplete或onError。延迟时,你可以产生一个observable,它永远不会像在Observable.never()中那样结束。
是的,异常将被捕获并传递为onError。您可以立即在链中使用操作符处理错误,也可以在订阅时提供onError句柄(重载)。
如果您使用的是RxJava1.x,则可能会在流中遇到空值,因为使用onNext(null)传递值是有效的。因此,由于NPE的可能性,您需要进行空检查。您可以使用filter-operator过滤掉null值,而不是使用null检查:
Observable.just("1", "2", null, "3")
.filter(s -> s != null)
.map(s -> s.getBytes())
.subscribe(bytes -> {
//...
});
在这种情况下,您将收到有关s.getBytes()可能的NPE的警告。但是由于过滤操作,你可以肯定,s永远不会为空。