RxJava 线程不等待结果
RxJava thread not waiting for result
我有这个方法,我试图从 API 中提取数据,然后更新文本视图。在 "end Method" log. .getRecipeName()
使用 RetroFit 从 API.
中提取后,一切正常,除了 getRecipeName 没有完成
我目前正在使用 MVP、Dagger、RxJava 和 Butterknife 同时学习
Mindork's Github page on MVP Architecture
我注释掉了 .subscribeOn 和 .observeOn 以查看结果差异,但没有任何变化。
@Override
public void onRandomButtonClicked() {
getMvpView().showLoading();
Log.e(TAG, "Random Method Open");
getCompositeDisposable().add(getDataManager()
.getRecipeName()
//.subscribeOn(getSchedulerProvider().io())
//.observeOn(getSchedulerProvider().ui())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.e(TAG, "accept");
getMvpView().updateTextView(title);
}
}));
Log.e(TAG, "end method");
}
这是我的 getRecipeName() 方法
@Override
public Observable<String> getRecipeName() {
/*Create handle for the RetrofitInstance interface*/
GetDataService service = RetrofitClientInstance.getRetrofitInstance().create(GetDataService.class);
Call<RecipeList> call = service.getRecipe();
call.enqueue(new Callback<RecipeList>() {
@Override
public void onResponse(@NonNull Call<RecipeList> call, @NonNull retrofit2.Response<RecipeList> response) {
Log.e("onResponse","Recipe is Successful = " + response.isSuccessful());
//if response is false then skip to avoid null object reference
if (response.isSuccessful()) {
RecipeList drinkRecipe = response.body();
List<Recipe> recipes = drinkRecipe.getDrinks();
jokeText = String.valueOf(recipes.size());
Recipe myRecipe = recipes.get(0);
jokeText = myRecipe.getStrDrink();
Log.e("On Response", "Result2: " + jokeText);
}
//jokeText = "null";
}
@Override
public void onFailure(Call<RecipeList> call, Throwable t) {
Log.e("On Response","Failure");
}
});
//return jokeText;
return Observable.fromCallable(new Callable<String>() {
@Override
public String call() throws Exception {
return jokeText;
}
});
}
解决方案
正如评论所说,RxJava Adapter 是正确的方法。我将使用适配器 post 我自己的工作代码。我发现很难找到一个工作示例。
//single api call using retrofit and rxjava
@SuppressLint("CheckResult")
private void getRandomButtonClick(){
retrofit = RetrofitClientInstance.getRetrofitInstance();
retrofit.create(GetDataService.class).getRecipe()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::handleResults, this::handleError );
}
private void handleResults(RecipeList recipeList) {
int i = recipeList.getDrinks().size();
Log.e(TAG, "size is: "+ i);
Recipe recipe = recipeList.getDrinks().get(0);
getMvpView().updateTextView(recipe.getStrDrink());
}
private void handleError(Throwable t){
Log.e("Observer", "");
}
我的 Retrofit 客户端实例
public static Retrofit getRetrofitInstance() {
if (retrofit == null) {
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
return retrofit;
}
我的界面
public interface GetDataService {
//@Headers({})
@GET("random.php")
Observable<RecipeList> getRecipe();
我找到了一个很好的参考资源来帮助我正确地实现它。 Retrofit Android
原因是因为您的 observable 每次被订阅时都会返回 jokeText。它returns在调用后立即执行,不会等待您的网络操作。
一种可能的解决方案是使用 RxJavaCallAdapter。 Link 这里:https://github.com/square/retrofit/tree/master/retrofit-adapters/rxjava2
它会自动将您的 API returns 转换为可观察对象。无需手动调用改造请求。只需处理响应并将其从那里转换为您想要的对象。
另一种方法是将整个序列包装在 Observable.create
或 Observable.fromAsync
.
中
我有这个方法,我试图从 API 中提取数据,然后更新文本视图。在 "end Method" log. .getRecipeName()
使用 RetroFit 从 API.
我目前正在使用 MVP、Dagger、RxJava 和 Butterknife 同时学习 Mindork's Github page on MVP Architecture
我注释掉了 .subscribeOn 和 .observeOn 以查看结果差异,但没有任何变化。
@Override
public void onRandomButtonClicked() {
getMvpView().showLoading();
Log.e(TAG, "Random Method Open");
getCompositeDisposable().add(getDataManager()
.getRecipeName()
//.subscribeOn(getSchedulerProvider().io())
//.observeOn(getSchedulerProvider().ui())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.e(TAG, "accept");
getMvpView().updateTextView(title);
}
}));
Log.e(TAG, "end method");
}
这是我的 getRecipeName() 方法
@Override
public Observable<String> getRecipeName() {
/*Create handle for the RetrofitInstance interface*/
GetDataService service = RetrofitClientInstance.getRetrofitInstance().create(GetDataService.class);
Call<RecipeList> call = service.getRecipe();
call.enqueue(new Callback<RecipeList>() {
@Override
public void onResponse(@NonNull Call<RecipeList> call, @NonNull retrofit2.Response<RecipeList> response) {
Log.e("onResponse","Recipe is Successful = " + response.isSuccessful());
//if response is false then skip to avoid null object reference
if (response.isSuccessful()) {
RecipeList drinkRecipe = response.body();
List<Recipe> recipes = drinkRecipe.getDrinks();
jokeText = String.valueOf(recipes.size());
Recipe myRecipe = recipes.get(0);
jokeText = myRecipe.getStrDrink();
Log.e("On Response", "Result2: " + jokeText);
}
//jokeText = "null";
}
@Override
public void onFailure(Call<RecipeList> call, Throwable t) {
Log.e("On Response","Failure");
}
});
//return jokeText;
return Observable.fromCallable(new Callable<String>() {
@Override
public String call() throws Exception {
return jokeText;
}
});
}
解决方案
正如评论所说,RxJava Adapter 是正确的方法。我将使用适配器 post 我自己的工作代码。我发现很难找到一个工作示例。
//single api call using retrofit and rxjava
@SuppressLint("CheckResult")
private void getRandomButtonClick(){
retrofit = RetrofitClientInstance.getRetrofitInstance();
retrofit.create(GetDataService.class).getRecipe()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::handleResults, this::handleError );
}
private void handleResults(RecipeList recipeList) {
int i = recipeList.getDrinks().size();
Log.e(TAG, "size is: "+ i);
Recipe recipe = recipeList.getDrinks().get(0);
getMvpView().updateTextView(recipe.getStrDrink());
}
private void handleError(Throwable t){
Log.e("Observer", "");
}
我的 Retrofit 客户端实例
public static Retrofit getRetrofitInstance() {
if (retrofit == null) {
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
return retrofit;
}
我的界面
public interface GetDataService {
//@Headers({})
@GET("random.php")
Observable<RecipeList> getRecipe();
我找到了一个很好的参考资源来帮助我正确地实现它。 Retrofit Android
原因是因为您的 observable 每次被订阅时都会返回 jokeText。它returns在调用后立即执行,不会等待您的网络操作。
一种可能的解决方案是使用 RxJavaCallAdapter。 Link 这里:https://github.com/square/retrofit/tree/master/retrofit-adapters/rxjava2
它会自动将您的 API returns 转换为可观察对象。无需手动调用改造请求。只需处理响应并将其从那里转换为您想要的对象。
另一种方法是将整个序列包装在 Observable.create
或 Observable.fromAsync
.