2016-02-16 6 views
4

Я отправляю несколько перенастроенных вызовов через SyncAdapter onPerformSync, и я пытаюсь настроить HTTP-вызовы, отправив их через инструкцию try/catch sleep. Однако это блокирует пользовательский интерфейс и не будет реагировать только после завершения всех вызовов.Регулировка сетевых вызовов в 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", а не в потоке Main UI. Однако это может измениться при создании асинхронных вызовов с обратными вызовами (что здесь наш случай).

Здесь вы используете асинхронный вызов метода «call.enqueue» «Дооснащение», и это влияет на выполнение потока. На вопрос, который мы должны задать на этом этапе:

Где будут выполняться методы обратного вызова?

Чтобы получить ответ на этот вопрос, мы должны определить, какие Looper будет использоваться Handler, который будет размещать обратные вызовы.

В случае, если мы сами играем с обработчиками, мы можем определить петлитель, обработчик и способы обработки сообщений/runnables между обработчиками. Но на этот раз все по-другому, потому что мы используем стороннюю структуру (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()", что означает, что дооснащения будет отправлять сообщения/runnables в основной поток очередь сообщений (вы можете провести исследование по этому вопросу для дальнейшего подробного объяснения). Таким образом, опубликованное сообщение/runnable будет обрабатываться основным потоком.

Так, чтобы, будучи сказанным, , обратные вызовы onResponse/onFailure будут выполнены в основном потоке. И это заблокирует пользовательский интерфейс, если вы делаете слишком много работы (Thread.sleep (SLEEP_TIME);). Вы можете проверить его самостоятельно: просто сделайте контрольную точку в обратном вызове onResponse и проверьте, в каком потоке она запущена.

Как справиться с этой ситуацией? (Ответ на ваш вопрос об использовании Retrofit)

Поскольку мы уже в фоновом потоке (SyncAdapterThread), так что нет необходимости делать асинхронные вызовы в вашем случае. Просто выполните синхронный вызов «Дооснастить», а затем обработайте результат или зарегистрируйте сбой. Таким образом, вы не будете блокировать пользовательский интерфейс.

+0

Спасибо за ваш ответ. В настоящий момент я просматриваю вызовы синхронизации «Модернизация». –

 Смежные вопросы

  • Нет связанных вопросов^_^