【问题标题】:SubscribeOn(Schedulers.io()) + blockingGet() = UI skipped framesSubscribeOn(Schedulers.io()) + blockingGet() = UI 跳帧
【发布时间】:2017-11-12 16:40:24
【问题描述】:

我为远程 API 编写了一个 TokenManager 的 RxJava 实现(我通过 Retrofit 使用它)。但是我遇到了一个障碍,即使我 subscribeOn(Schedulers.io()) 使用 blockingGet() 调用方法会导致 UI 帧被跳过

基本上,我已将getToken() 作为参数包含在API 的search() 调用方法中。如果令牌存在,则会提供,如果不存在,则会通过 API token() 调用获取。 Choreographer skipped frames!! 消息)

寻找有关如何纠正跳帧的建议,或有关如何更好地实现此代码的建议。

ListFetcher(调用TokenManagergetToken()的类)

public Single<List<Business>> getList(final String latitude, final String longitude) {
    return api
            .search(
                    tokenManager.getToken(),  // <-- Here's the TokenManager reference
                    AppSettings.SEARCH_TERM,
                    latitude,
                    longitude,
                    AppSettings.SEARCH_RADIUS,
                    Yelp3Api.SEARCH_LIMIT)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .flatMap(searchResponse -> {
                if (searchResponse.getBusinesses().size() < searchResponse.getTotal()) {
                    return subsequentSearchCalls(searchResponse, latitude, longitude)
                            .map(businesses -> {
                                List<Business> list = new ArrayList<>();
                                list.addAll(searchResponse.getBusinesses());
                                list.addAll(businesses);
                                return list;
                            });
                } else {
                    return Single.just(searchResponse.getBusinesses());
                }
            });
}

令牌管理器getToken()

public synchronized String getToken() {
    final String cachedToken = sharedPrefs.getString(tokenKey, "null");
    if (cachedToken.equals("null")) {
        String tokenString = api
                .token(
                        Yelp3Api.GrantType.CLIENT_CREDENTIALS,
                        BuildConfig.YELPFUSION_CLIENT_ID,
                        BuildConfig.YELPFUSION_CLIENT_SECRET)
                .subscribeOn(Schedulers.io())
                .doOnSuccess(this::setSharedPrefToken)
                .map(tokenResponse -> String.format(AUTH_FORMAT, tokenResponse.getAccessToken()))
                .blockingGet();
        return tokenString;
    } else {
        return String.format(AUTH_FORMAT, cachedToken);
    }
}

Yelp3Api(改造界面)

@FormUrlEncoded
@POST("oauth2/token")
Single<TokenResponse> token(
        @Field("grant_type") String grantType,
        @Field("client_id") String clientId,
        @Field("client_secret") String clientSecret
);

@GET("v3/businesses/search")
Single<SearchResponse> search(
        @Header("Authorization") String authorization,
        @Query("term") String term,
        @Query("latitude") String latitude,
        @Query("longitude") String longitude,
        @Query("radius") int radius,
        @Query("limit") int limit
);

【问题讨论】:

    标签: android retrofit2 rx-java2


    【解决方案1】:

    当您调用getToken() 时,它不会延迟执行。它在您的 UI 线程上执行阻塞调用。 要修复它,请将 getToken 包装在 Single.fromCallableflatMap 上面 api.search()

    希望这能弄清楚实际发生的事情

    【讨论】:

    • 谢谢。这是执行非 Rx 代码的正确方法,而不是使用 blockingGet()just() 我还发现这个视频很有帮助:caster.io/lessons/…
    【解决方案2】:

    我最终使用okhttp authenticator 来请求身份验证凭据并使用okhttp interceptor 将身份验证标头添加到传出请求中重新编写。

    根据the internet,这似乎是一个更好的实现。

    但是我接受@Tuby 的回答,因为它是对原始问题的更直接的解决方案。

    【讨论】:

      猜你喜欢
      • 2019-03-24
      • 2018-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多