在执行另一个Observable之前等待Observable完成?

时间:2016-10-20 23:09:35

标签: android rx-java rx-android

问题

我有一个活动,它定期从API获取数据并显示收到的数据。 API使用OAuth,因此我收到一个临时访问令牌,该令牌在一段时间(1小时)后过期。如果应用程序尝试使用过期令牌获取数据,则显然请求将失败。在我的应用程序的早期版本中,我使用AsyncTasks作为网络请求,并且基本上只执行了一个新的AsyncTask,它将在调用从服务器获取数据的主AsyncTask之前获得新的访问令牌。这很有效,因为主AsyncTask会等到另一个完成后再执行。

我最近切换到RxJava,基本上只是用Observables替换了AsyncTasks。问题是获取数据的主要Observable不会等待刷新访问令牌完成的Observable。这是我的代码,谢谢你的帮助。

代码

LiveThreadActivity.java

private Subscription subscription;
private Observable<List<CustomComment>> fetchData;

@Override
protected void onResume() {
    super.onResume();

    if (tokenExpired()) {
        auth.refreshToken();
    }

    subscription = fetchData
            .compose(bindToLifecycle())
            .retryWhen(new RetryWithDelay(5, 2000))
            .subscribe(list -> addNewComments(list), e -> handleFetchDataError(e));

}


// This method gets called in onCreate()
private void dataCollection() {
    fetchData = Observable.interval(0, REFRESH_RATE, TimeUnit.MILLISECONDS)
            .map(tick -> fetchNewComments())            // Run function every time a tick is emitted
            .retryWhen( new RetryWithDelay(2, 2000) )   // Retry twice with 2 second delay
            .subscribeOn(Schedulers.io())               // Network stuff in background thread
            .observeOn(AndroidSchedulers.mainThread()); // Other stuff on the main thread

}

Auth.java

public class Auth {
    ...

    public void refreshToken() {
        Observable.just(1)
                .map(y -> refreshAccessToken())
                .retryWhen( new RetryWithDelay(3, 2000) )
                .subscribeOn(Schedulers.io())
                .subscribe();
    }
}

2 个答案:

答案 0 :(得分:3)

使用反应库需要一种新的思维方式。你必须编写同步的代码,但要注意它是异步的。

您的代码只是同步执行。它同时执行两个using (StreamReader file = File.OpenText(path)) { JsonSerializer jsonSerializer = new JsonSerializer { NullValueHandling = NullValueHandling.Ignore }; object person = (object)jsonSerializer.Deserialize(file, typeof(List<PersonList>)); }

函数Observable应如下所示:

refreshToken()

public Observable<?> refreshToken() { return Observable.just(1) .map(y -> refreshAccessToken()) .retryWhen( new RetryWithDelay(3, 2000) ) .subscribeOn(Schedulers.io()); }

onResume()

注意@Override protected void onResume() { super.onResume(); Observable obs = fetchData .compose(bindToLifecycle()) .retryWhen(new RetryWithDelay(5, 2000)); if (tokenExpired()) { obs = obs.startWith(auth.refreshToken()); } subscription = obs .subscribe(list -> addNewComments(list), e -> handleFetchDataError(e)); } 运营商。它允许一个接一个地执行startWith()(提取列表)(刷新令牌)。

答案 1 :(得分:0)

.flatMap()可能就足够了,即tokenObservable.flatMap(/ * return dataObservable * /)