我想在另一个线程(如IO线程)中使用okhttp请求一个url并在Android主线程中获取UIView* alertSubView = [alertView valueForKey:@"accessoryView"];
,但我不知道如何创建Response
答案 0 :(得分:25)
首先将RxAndroid
添加到您的依赖项,然后像这样创建Observable
:
Subscription subscription = Observable.create(new Observable.OnSubscribe<Response>() {
OkHttpClient client = new OkHttpClient();
@Override
public void call(Subscriber<? super Response> subscriber) {
try {
Response response = client.newCall(new Request.Builder().url("your url").build()).execute();
if (response.isSuccessful()) {
if(!subscriber.isUnsubscribed()){
subscriber.onNext(response);
}
subscriber.onCompleted();
} else if (!response.isSuccessful() && !subscriber.isUnsubscribed()) {
subscriber.onError(new Exception("error"));
}
} catch (IOException e) {
if (!subscriber.isUnsubscribed()) {
subscriber.onError(e);
}
}
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Response>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Response response) {
}
});
它会在另一个线程(io线程)中请求你的url并在android主线程上观察它。
最后当您离开屏幕时使用subsribtion.unsubscribe()
以避免内存泄漏。
当你使用Observable.create
时,你应该编写很多样板代码,你也必须自己处理订阅。更好的选择是使用defer。
形成文档:
在观察者订阅并创建之前不要创建Observable 为每个观察者提供一个新的观察者
Defer运算符等待观察者订阅它,然后 它生成一个Observable,通常带有一个Observable工厂 功能。它为每个用户重新做这件事,所以尽管每个用户都这样做 订阅者实际上可能认为它订阅了相同的Observable 每个订户都有自己独立的序列。
提到Marcin Koziński时,您只需要这样做:
final OkHttpClient client = new OkHttpClient();
Observable.defer(new Func0<Observable<Response>>() {
@Override public Observable<Response> call() {
try {
Response response = client.newCall(new Request.Builder().url("your url").build()).execute();
return Observable.just(response);
} catch (IOException e) {
return Observable.error(e);
}
}
});
答案 1 :(得分:18)
使用Observable.defer()
代替Observable.create()
更容易,更安全:
final OkHttpClient client = new OkHttpClient();
Observable.defer(new Func0<Observable<Response>>() {
@Override public Observable<Response> call() {
try {
Response response = client.newCall(new Request.Builder().url("your url").build()).execute();
return Observable.just(response);
} catch (IOException e) {
return Observable.error(e);
}
}
});
这样就可以为您处理取消订阅和背压。这里有this library create()
和defer()
。
如果您希望使用Observable.create()
路线,那么它看起来应该更像https://api.github.com/users/octocat,其中isUnsubscribed()
个电话随处可见。而且我相信这仍然无法处理背压。
答案 2 :(得分:10)
我意识到这篇文章有点陈旧,但现在有一种新的,更方便的方法
Observable.fromCallable {
client.newCall(Request.Builder().url("your url").build()).execute()
}
更多信息:https://artemzin.com/blog/rxjava-defer-execution-of-function-via-fromcallable/
答案 3 :(得分:0)
我来不及进行讨论,但是,如果由于某种原因代码需要流式传输响应主体,那么defer
或fromCallable
就不会这样做。相反,可以使用using
运算符。
Single.using(() -> okHttpClient.newCall(okRequest).execute(), // 1
response -> { // 2
...
return Single.just((Consumer<OutputStream>) fileOutput -> {
try (InputStream upstreamResponseStream = response.body().byteStream();
OutputStream fileOutput = responseBodyOutput) {
ByteStreams.copy(upstreamResponseStream, output);
}
});
},
Response::close, // 3
false) // 4
.subscribeOn(Schedulers.io()) // 5
.subscribe(copier -> copier.accept(...), // 6
throwable -> ...); // 7
Single.just(...)
defer
可以使用try-with-resources样式。eager
开关设置为false
,以在终端事件之后(即在执行订阅使用者之后)调用该处置程序。eager
设置为false
,则代码将引发IOException,原因为“ closed”,因为在输入此lambda之前,响应已经关闭。onError
lambda应该处理异常,特别是IOException
不能再捕获的using
,因为使用defer
进行try / catch可以实现。 答案 4 :(得分:0)
带有RxSingle后台API调用的Okhttp3。
Disposable disposables = Single.fromCallable(() -> {
Log.e(TAG, "clearData: Thread[" + Thread.currentThread().getName() + "]");
OkHttpClient client = Util.getHttpClient();
Request request = new Request.Builder()
.addHeader("Authorization", "Bearer " + Util.getUserToken())
.url(BuildConfig.BASE_URL + ApiConstants.DELETE_FEEDS)
.build();
Response response = client.newCall(request).execute();
if(response.isSuccessful()) {
...
return ; // Any type
} else {
return ; // Any type
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe((result) -> {
Log.d(TAG, "api() completed");
});
compositeDisposable.add(disposables);