2016-02-16 33 views
4

我通过SyncAdapter onPerformSync发送多个翻新调用,并试图通过try/catch休眠语句发送来调节http调用。但是,这会阻止用户界面,并且只有在完成所有调用后才会响应。在SyncAdapter onPerformSync中规范网络调用

什么是更好的方式来调节onPerformSync中的网络调用(使用睡眠定时器)后台在不阻止用户界面?

@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()); 
      } 
     }); 
    } 
} 

回答

5

“onPerformSync”代码在“SyncAdapterThread”线程中执行,而不是在主UI线程中执行。然而,当使用回调进行异步调用时(这是我们的情况),这可能会改变。

这里您使用的是Retrofit“call.enqueue”方法的异步调用,这对线程执行有影响。我们现在需要问的问题:

回调方法将在哪里执行?

要得到这个问题的答案,我们必须确定哪些尺蠖是要由处理器将回调后使用。

如果我们自己处理处理程序,我们可以定义循环程序,处理程序以及如何处理处理程序之间的消息/可运行程序。但是这次它是不同的,因为我们正在使用第三方框架(Retrofit)。所以我们必须知道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); 
     } 
    } 
    } 

可以通知“Looper.getMainLooper()”,这意味着将改造张贴消息/可运行成主线程消息队列(你可以对此做进一步的详细解释)。因此,发布的消息/ runnable将由主线程处理。

这样说,onResponse/onFailure回调将在主线程中执行。如果你做了太多工作(Thread.sleep(SLEEP_TIME);),它将阻止用户界面。您可以自己检查:只需在“onResponse”回调中创建一个断点并检查它正在运行的线程。

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

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

+0

感谢您的回答。我现在正在调查Retrofit同步调用。 –