在 onDoNext 和 doOnCompleted 方法中难以设置视图
Difficulty setting view in onDoNext and doOnCompleted methods
我正在学习 RxAndroid,并从我项目中的一个非常简单的示例开始。即获取用户个人资料图像 URL 可观察到的响应。
下面是获取字符串URL值的代码,我用Picasso加载图片URL。当我使用 运行onUiThread 加载图像时代码工作正常,但是当我不使用它时它会抛出错误;它说方法调用应该在主线程中。
总是在后台线程上执行 doOnNext 和 doOnCompleted 运行?
picUrlSubscription = getUrlAsObservable()
.map(responseBodyResponse -> {
Log.d(TAG, "map ");
try {
if (responseBodyResponse.isSuccessful()) {
observableStr = responseBodyResponse.body().string();
return observableStr;
} else {
observableStr = "Bad_url";
return observableStr;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
})
.doOnNext(s -> {
Log.d(TAG, "next ");
try {
if (s != null && !s.equalsIgnoreCase("Bad_url")) {
observableStr = new JSONObject(s).getString("url");
} else
runOnUiThread(() -> profileCircle.setImageResource(R.drawable.profil));
} catch (JSONException e) {
e.printStackTrace();
runOnUiThread(() -> profileCircle.setImageResource(R.drawable.profil));
}
})
.doOnCompleted(() -> {
Log.d(TAG, "completed ");
runOnUiThread(() -> Picasso.with(this).load(observableStr).into(profileCircle));
})
.onErrorReturn(throwable -> {
Log.d(TAG, "error "+ throwable.getMessage());
observableStr = "bad_url";
runOnUiThread(() -> profileCircle.setImageResource(R.drawable.profil));
return observableStr;
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe();
否,doOnNext()
和 doOnCompleted()
运行 在指定的线程上通知其观察者。如果未指定线程,它们将 运行 在 observable 正在运行的同一线程上。
由于您指定了 subscribeOn(Schedulers.io())
,可观察对象将在 io
线程上运行。根据 documentation; subscribeOn()
运算符指定可观察对象将在哪个线程上运行,无论它出现在链中的哪个位置,这与 observeOn()
运算符不同:
ObserveOn
, on the other hand, affects the thread that the Observable
will use below where that operator appears.
因此,将您的 observeOn()
调用 放在 您的 doOnNext()
和 doOnCompleted()
调用之前。
虽然这个问题得到了回答,但就 RX 实践而言,我发现此代码存在许多问题。
主要问题是错误处理 - 如果可能的话,您应该避免在运算符内部处理异常,而应该在订阅者中进行。在下面的代码中,我通过始终在订阅者的 onError
部分设置配置文件默认图像来从您的代码中删除了很多重复项。
我还鼓励您避免使用 doOnNext
/ doOnCompleted
/ doOnError
- 如果您想添加一些副作用,这些运算符很好您的 RX 链(例如,调用您的分析跟踪)——而是使用订阅者——它的用途是什么。在订阅者中进行错误处理尤为重要 - 如果出现您没有想到的错误,它将防止您的应用程序崩溃。
运算符跳线。如果您希望在不同的线程上执行操作,请使用 subscribeOn
/observeOn
这是包含我的建议的代码:
picUrlSubscription = getUrlAsObservable()
.map(responseBodyResponse -> {
String jsonString = null;
if (responseBodyResponse.isSuccessful()) {
try {
jsonString = responseBodyResponse.body().string();
} catch (IOException e) {
throw new RuntimeException("Failed decoding response!");
}
} else {
throw new RuntimeException("Bad request URL!");
}
return jsonString;
})
.map(jsonString -> {
String profileUrl = null;
if (jsonString != null) {
profileUrl = new JSONObject(jsonString).getString("url");
}
if (profileUrl == null || profileUrl.isEmpty()) {
throw new RuntimeException("Profile URL missing in response!");
}
return profileUrl;
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(profileUrl -> Picasso.with(this).load(profileUrl).into(profileCircle),
throwable -> {
Log.e("TAG", "Failed loading profile image!", throwable);
profileCircle.setImageResource(R.drawable.profil);
});
我正在学习 RxAndroid,并从我项目中的一个非常简单的示例开始。即获取用户个人资料图像 URL 可观察到的响应。
下面是获取字符串URL值的代码,我用Picasso加载图片URL。当我使用 运行onUiThread 加载图像时代码工作正常,但是当我不使用它时它会抛出错误;它说方法调用应该在主线程中。
总是在后台线程上执行 doOnNext 和 doOnCompleted 运行?
picUrlSubscription = getUrlAsObservable()
.map(responseBodyResponse -> {
Log.d(TAG, "map ");
try {
if (responseBodyResponse.isSuccessful()) {
observableStr = responseBodyResponse.body().string();
return observableStr;
} else {
observableStr = "Bad_url";
return observableStr;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
})
.doOnNext(s -> {
Log.d(TAG, "next ");
try {
if (s != null && !s.equalsIgnoreCase("Bad_url")) {
observableStr = new JSONObject(s).getString("url");
} else
runOnUiThread(() -> profileCircle.setImageResource(R.drawable.profil));
} catch (JSONException e) {
e.printStackTrace();
runOnUiThread(() -> profileCircle.setImageResource(R.drawable.profil));
}
})
.doOnCompleted(() -> {
Log.d(TAG, "completed ");
runOnUiThread(() -> Picasso.with(this).load(observableStr).into(profileCircle));
})
.onErrorReturn(throwable -> {
Log.d(TAG, "error "+ throwable.getMessage());
observableStr = "bad_url";
runOnUiThread(() -> profileCircle.setImageResource(R.drawable.profil));
return observableStr;
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe();
否,doOnNext()
和 doOnCompleted()
运行 在指定的线程上通知其观察者。如果未指定线程,它们将 运行 在 observable 正在运行的同一线程上。
由于您指定了 subscribeOn(Schedulers.io())
,可观察对象将在 io
线程上运行。根据 documentation; subscribeOn()
运算符指定可观察对象将在哪个线程上运行,无论它出现在链中的哪个位置,这与 observeOn()
运算符不同:
ObserveOn
, on the other hand, affects the thread that theObservable
will use below where that operator appears.
因此,将您的 observeOn()
调用 放在 您的 doOnNext()
和 doOnCompleted()
调用之前。
虽然这个问题得到了回答,但就 RX 实践而言,我发现此代码存在许多问题。
主要问题是错误处理 - 如果可能的话,您应该避免在运算符内部处理异常,而应该在订阅者中进行。在下面的代码中,我通过始终在订阅者的
onError
部分设置配置文件默认图像来从您的代码中删除了很多重复项。我还鼓励您避免使用
doOnNext
/doOnCompleted
/doOnError
- 如果您想添加一些副作用,这些运算符很好您的 RX 链(例如,调用您的分析跟踪)——而是使用订阅者——它的用途是什么。在订阅者中进行错误处理尤为重要 - 如果出现您没有想到的错误,它将防止您的应用程序崩溃。运算符跳线。如果您希望在不同的线程上执行操作,请使用
subscribeOn
/observeOn
这是包含我的建议的代码:
picUrlSubscription = getUrlAsObservable()
.map(responseBodyResponse -> {
String jsonString = null;
if (responseBodyResponse.isSuccessful()) {
try {
jsonString = responseBodyResponse.body().string();
} catch (IOException e) {
throw new RuntimeException("Failed decoding response!");
}
} else {
throw new RuntimeException("Bad request URL!");
}
return jsonString;
})
.map(jsonString -> {
String profileUrl = null;
if (jsonString != null) {
profileUrl = new JSONObject(jsonString).getString("url");
}
if (profileUrl == null || profileUrl.isEmpty()) {
throw new RuntimeException("Profile URL missing in response!");
}
return profileUrl;
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(profileUrl -> Picasso.with(this).load(profileUrl).into(profileCircle),
throwable -> {
Log.e("TAG", "Failed loading profile image!", throwable);
profileCircle.setImageResource(R.drawable.profil);
});