2017-02-10 13 views
1

Я использую RxJava и Retrofit в приложении для Android, чтобы получить данные с сервера. У меня есть тестовая активность с этим кодом.Rx Android - дождаться ответа сервера

String text; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     viewMenu = (LinearLayout) findViewById(R.id.view_menu); 
     tabMenu.initTabBar(viewMenu, this); 
     CapabilitiesHolder.createIfNotExist().getCapabilities().subscribe(this::handleResponse, RestErrorHandler::handle); 
     Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); 
    } 



    private void handleResponse(CapabilitiesResponse capabilitiesResponse) { 
     if (capabilitiesResponse.isSuccess()) { 
      text = capabilitiesResponse.getSupportedCurrencies().get(0).getDescription(); 
     } else { 
      RestErrorHandler.handle(null, capabilitiesResponse); 
     } 
    } 

И класс Singleton для хранения данных с сервера в течение всего жизненного цикла приложения.

public class CapabilitiesHolder { 


    private static CapabilitiesHolder mInstance = null; 

    private CapabilitiesResponse capabilities; 


    public static CapabilitiesHolder createIfNotExist() { 
     if (mInstance == null) { 
      mInstance = new CapabilitiesHolder(); 
     } 
     return mInstance; 
    } 

    private CapabilitiesHolder() { 
     requestCapabilities(); 
    } 

    public Observable<CapabilitiesResponse> getCapabilities() { 
     return Observable.fromCallable(() -> capabilities); 
    } 

    private CompositeSubscription compositeSubscription = new CompositeSubscription(); 

    private void requestCapabilities() { 
     Observable<CapabilitiesResponse> o = RestServiceFactory.get().getServerCapabilities(); 
     compositeSubscription.add(o.subscribe(this::handleResponse, RestErrorHandler::handle)); 
    } 

    private void handleResponse(CapabilitiesResponse capabilitiesResponse) { 
     if (capabilitiesResponse.isSuccess()) { 
      capabilities = capabilitiesResponse; 
     } else { 
      RestErrorHandler.handle(null, capabilitiesResponse); 
     } 
    } 

    public void update() { 
     mInstance = null; 
     mInstance = new CapabilitiesHolder(); 
    } 
} 

Так что, когда мой тест активности создали первый раз, и сразу же призывает к CapabilitiesHolder.createIfNotExist().getCapabilities() Тост пуст, так как данные в ответ требуется некоторое время, чтобы загрузить. Когда onCreate называется немного позже, все в порядке.

Вопрос в том, может ли я сделать (используя RxJava?) getCapabilities() метод ждать ответа от сервера, прежде чем его вызывать.

Заранее благодарен!

ответ

1

Короткий ответ - не блокируйте поток пользовательского интерфейса и ничего не ждите.

Переместите Тост в метод, который обрабатывает ответ

private void handleResponse(CapabilitiesResponse capabilitiesResponse) { 
    if (capabilitiesResponse.isSuccess()) { 
     text = capabilitiesResponse.getSupportedCurrencies().get(0).getDescription(); 
     // Toast here 
    } else { 
     RestErrorHandler.handle(null, capabilitiesResponse); 
    } 
+0

Благодарим за консультацию. Но, как я уже упоминал, это тестовая активность, поэтому Toast будет вообще удалена. Основной вопрос заключался в том, как я могу сделать 'CapabilitiesHolder.createIfNotExist(). GetCapabilities()' this, чтобы вернуть результат, когда он готов, вместо того, чтобы возвращать «null» после первого вызова. –

+1

Он не возвращает значение null. Метод getCapabilities не блокирует (и не должен). Запрос просто не закончился в точке вашего метода Toast. –

+1

У вашего обработчика обратного вызова установлен ответ. Не имеет значения, если вы поджариваете или обновляете свой пользовательский интерфейс. Вот что я говорю –

1

Я предлагаю вам восстановить ваш класс класса CapabilitiesHolder. Если вы хотите использовать этот держатель, вы не должны запрашивать какие-либо данные внутри конструктора. Также блокирование потока пользовательского интерфейса: Плохая практика.

private CapabilitiesHolder() { 
    //empty 
} 

public Observable<CapabilitiesResponse> getCapabilities() { 
    if(capabilities!=null){ 
     return Observable.fromCallable(() -> capabilities); 
    } else { 
     return RestServiceFactory.get() 
       .getServerCapabilities() 
       .doOnNext(capabilitiesResponse -> capabilities = capabilitiesResponse); 
    } 
}