2016-02-16 37 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同步調用。 –