RXJava 改造等待 UI 等待从 API 获取数据
RXJava retrofit waiting having the UI wait for data to be fetched from API
我正在学习 android 开发 我正在使用 RXJava 进行改造以与 API 进行交互。所以我已经成功地从我的 API 中获取了数据。现在的问题是程序在获取数据之前继续执行。我怎样才能等待数据从 API 下载然后 运行 一些函数?
我有一个改装客户端,如图所示
public class RetrofitClient {
private static Retrofit retrofit = null;
private RetrofitClient() {
}
public static Retrofit getClient(String baseUrl) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(SimpleXmlConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
}
return retrofit;
}
}
我这样调用 API。
public void getData(MyFragment Fragment) {
mAPIService.getData()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Data>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.i("ERROR IN GET DATA", e.toString());
}
@Override
public void onNext(Data response) {
Log.i("MY DATA", response.toString());
fragment.downloadData(response);
}
});
}
问题是我的 android 应用程序没有等待 fragment.downloadData(响应)完成,而是继续执行代码,然后因为响应为空而崩溃。
我在按钮上有一个侦听器,单击该按钮会从 API
获取数据
button.setOnClickListener(v ->{
APICaller.getData(this);
Log.i("TEST", data.ToString()); //THIS IS NULL
});
这是我 运行 来自 APICaller
的 downloadData 函数
public void downloadData(Data data) {
this.data = data;
}
您需要等待 RxJava 流发出值(错误或响应)。
首先,为此,如果您期望 "single" 发射,成功或失败,我会使用 Single
。目前看来您的 mAPIService.getData()
方法正在 returning 一个 Observable
。这些适用于将要发出多个值的流,在你的原因中我假设这不是将要发生的事情。您只有一个要发出的项目,所以我会查看 returning a Single
。不属于您的问题,仅供参考。
我喜欢做的是告诉我的 UI 无论我在做什么都是 "loading",通常在 doOnSubscribe
中。然后 UI 知道显示加载图标或不允许用户交互或其他内容。像这样的事情(注意。注意它是如何在 observeOn(AndroidSchedulers.mainThread)
之后的。任何时候你与 UI 元素交互,在主线程上进行。我认为这会做到):
mAPIService.getData()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
fragment.loading();
}
})
然后,当 onError
或 onSuccess
return 在您的订阅中时,这就是您告诉 UI 它已准备好继续的地方。然后您要么获得有效响应,要么可以向用户显示错误。
编辑:响应式编程
在你的评论之后,你似乎不了解响应式编程。它的学习曲线有点陡峭,我今天仍在努力学习它。
你的 APICaller
class,无论它是什么,都应该 return Observable
本身。你不应该将 Fragment
传递给它并在那里处理它,因为你正在打开自己的内存泄漏和它的一点代码气味。更好的选择是 return Observable
return 由 mAPIService.getData()
编辑。而已。目前你正在使用 Schedulers.io()
将 Observable
推到另一个线程,这对你的主线程说,继续,不要等我。然后,当使用代码 .observeOn(AndroidSchedulers.mainThread())
发出响应时,您会返回到此线程
然后在您的片段中处理值或错误的发出。您的片段代码将变为:
button.setOnClickListener(v ->{
APICaller.getData()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Data>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.i("ERROR IN GET DATA", e.toString());
}
@Override
public void onNext(Data response) {
Log.i("MY DATA", response.toString());
this.data = response
Log.i("TEST: "+data.toString());
}
});
});
我想推荐你看一些教程,做一些阅读,我还想让你回到我在开始时关于 Single
s 的观点
我正在学习 android 开发 我正在使用 RXJava 进行改造以与 API 进行交互。所以我已经成功地从我的 API 中获取了数据。现在的问题是程序在获取数据之前继续执行。我怎样才能等待数据从 API 下载然后 运行 一些函数?
我有一个改装客户端,如图所示
public class RetrofitClient {
private static Retrofit retrofit = null;
private RetrofitClient() {
}
public static Retrofit getClient(String baseUrl) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(SimpleXmlConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
}
return retrofit;
}
}
我这样调用 API。
public void getData(MyFragment Fragment) {
mAPIService.getData()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Data>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.i("ERROR IN GET DATA", e.toString());
}
@Override
public void onNext(Data response) {
Log.i("MY DATA", response.toString());
fragment.downloadData(response);
}
});
}
问题是我的 android 应用程序没有等待 fragment.downloadData(响应)完成,而是继续执行代码,然后因为响应为空而崩溃。
我在按钮上有一个侦听器,单击该按钮会从 API
获取数据 button.setOnClickListener(v ->{
APICaller.getData(this);
Log.i("TEST", data.ToString()); //THIS IS NULL
});
这是我 运行 来自 APICaller
的 downloadData 函数 public void downloadData(Data data) {
this.data = data;
}
您需要等待 RxJava 流发出值(错误或响应)。
首先,为此,如果您期望 "single" 发射,成功或失败,我会使用 Single
。目前看来您的 mAPIService.getData()
方法正在 returning 一个 Observable
。这些适用于将要发出多个值的流,在你的原因中我假设这不是将要发生的事情。您只有一个要发出的项目,所以我会查看 returning a Single
。不属于您的问题,仅供参考。
我喜欢做的是告诉我的 UI 无论我在做什么都是 "loading",通常在 doOnSubscribe
中。然后 UI 知道显示加载图标或不允许用户交互或其他内容。像这样的事情(注意。注意它是如何在 observeOn(AndroidSchedulers.mainThread)
之后的。任何时候你与 UI 元素交互,在主线程上进行。我认为这会做到):
mAPIService.getData()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
fragment.loading();
}
})
然后,当 onError
或 onSuccess
return 在您的订阅中时,这就是您告诉 UI 它已准备好继续的地方。然后您要么获得有效响应,要么可以向用户显示错误。
编辑:响应式编程
在你的评论之后,你似乎不了解响应式编程。它的学习曲线有点陡峭,我今天仍在努力学习它。
你的 APICaller
class,无论它是什么,都应该 return Observable
本身。你不应该将 Fragment
传递给它并在那里处理它,因为你正在打开自己的内存泄漏和它的一点代码气味。更好的选择是 return Observable
return 由 mAPIService.getData()
编辑。而已。目前你正在使用 Schedulers.io()
将 Observable
推到另一个线程,这对你的主线程说,继续,不要等我。然后,当使用代码 .observeOn(AndroidSchedulers.mainThread())
然后在您的片段中处理值或错误的发出。您的片段代码将变为:
button.setOnClickListener(v ->{
APICaller.getData()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Data>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.i("ERROR IN GET DATA", e.toString());
}
@Override
public void onNext(Data response) {
Log.i("MY DATA", response.toString());
this.data = response
Log.i("TEST: "+data.toString());
}
});
});
我想推荐你看一些教程,做一些阅读,我还想让你回到我在开始时关于 Single
s 的观点