Dmytro
Dmytro

Reputation: 2309

Rx Android - wait for server response

I use RxJava and Retrofit in an Android app to get data from server. I have test activity with this code.

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

And a Singleton class to contain data from server during whole lifecycle of the app.

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

So when my test Activity created first time, and immediately calls for CapabilitiesHolder.createIfNotExist().getCapabilities() the tost is empty, because data in response needs some time to be loaded. When onCreate called a bit later, everything's ok.

The question is, ho can I make (Using RxJava?) getCapabilities() method wait for response from server, before being called.

Thanks in advance!

Upvotes: 1

Views: 1102

Answers (2)

YMY
YMY

Reputation: 698

I'll suggest you to rebuild your class CapabilitiesHolder class. If you want to use that holder like that you should not request any data inside constructor. Also blocking UI thread is bad practice.

private CapabilitiesHolder() {
    //empty
}

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

Upvotes: 1

OneCricketeer
OneCricketeer

Reputation: 191701

Short answer - don't block the UI thread and wait for anything.

Move your Toast into the method that handles the response

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

Upvotes: 1

Related Questions