在SyncAdapter onPerformSync中调整网络调用

时间:2016-02-16 05:35:08

标签: android-syncadapter retrofit2

我通过SyncAdapter onPerformSync发送了几个改装调用,我试图通过try / catch sleep语句发送来调节http调用。但是,这会阻止UI,并且只有在完成所有调用后才会响应。

在onPerformSync的后台调节网络呼叫(使用睡眠定时器)而不阻止UI的更好方法是什么?

  @Override
  public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {

        String baseUrl = BuildConfig.API_BASE_URL;

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        service = retrofit.create(HTTPService.class);

        Call<RetroFitModel> RetroFitModelCall = service.getRetroFit(apiKey, sortOrder);
        RetroFitModelCall.enqueue(new Callback<RetroFitModel>() {
            @Override
            public void onResponse(Response<RetroFitModel> response) {
                if (!response.isSuccess()) {
                } else {
                    List<RetroFitResult> retrofitResultList = response.body().getResults();
                    Utility.storeList(getContext(), retrofitResultList);

                    for (final RetroFitResult result : retrofitResultList) {
                        RetroFitReview(result.getId(), service);

                        try {
                        // Sleep for SLEEP_TIME before running RetroFitReports & RetroFitTime
                            Thread.sleep(SLEEP_TIME);
                        } catch (InterruptedException e) {
                        }
                        RetroFitReports(result.getId(), service);
                        RetroFitTime(result.getId(), service);
                    }
                }
            }

            @Override
            public void onFailure(Throwable t) {
                Log.e(LOG_TAG, "Error: " + t.getMessage());
            }
        });
    }
}

1 个答案:

答案 0 :(得分:5)

&#34; onPerformSync&#34;代码在&#34; SyncAdapterThread&#34;中执行。线程,不在主UI线程内。但是,在使用回调进行异步调用时可能会发生这种情况(这是我们的例子)。

在这里,您正在使用Retrofit&#34; call.enqueue&#34;的异步调用。方法,这对线程执行有影响。我们现在需要提出的问题是:

  

哪里会执行回调方法?

要获得此问题的答案,我们必须确定将发布回调的处理程序将使用哪个 Looper

如果我们自己玩处理程序,我们可以定义looper,处理程序以及如何处理处理程序之间的消息/ runnables。但这次是不同的,因为我们正在使用第三方框架(Retrofit)。所以我们必须知道Retrofit使用哪个looper?

  

请注意如果Retrofit尚未定义他的looper,那么你   可能会遇到一个例外,说你需要一个活套   进程回调。换句话说,需要进行异步调用   一个looper线程,以便将回调发回给线程   它被执行的地方。

根据Retrofit(Platform.java)的代码来源:

static class Android extends Platform {
    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      if (callbackExecutor == null) {
        callbackExecutor = new MainThreadExecutor();
      }
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

您可以注意到&#34; Looper.getMainLooper()&#34;,这意味着Retrofit会将消息/ runnables发布到主线程消息队列中(您可以对此进行研究以获得进一步的详细说明)。因此,发布的消息/ runnable将由主线程处理。

所以说, onResponse / onFailure回调将在主线程中执行。如果你做了太多的工作,它会阻止UI(Thread.sleep(SLEEP_TIME);)。您可以自己检查:只需在&#34; onResponse&#34;中创建一个断点。回调并检查它正在运行的线程。

  

那么如何处理这种情况呢? (关于改造使用的问题的答案)

由于我们已经在后台线程(SyncAdapterThread)中,所以在您的情况下不需要进行异步调用。只需进行Retrofit同步调用,然后处理结果,或记录失败。 这样,您就不会阻止用户界面。