Reputation: 19
I resume my problem : I want to make webservice call (three calls), perform some operation on received data and finally update UI (many textview). I use retrofit2 and rxjava2 to perform webservice calls, specially Observable.zip() to make one time call for the three webservice in order to have all the three data before performing some calculation. The webservice call works well, but I have noticed that not all the instructions in my calculation method (in onComplete)are called, only the first textView.setText() is called, all that comes after is not executed. Even when I fill the method with only Log.i, not all of the are called. Same thing happens when I put the method in onNext() No error is thrown. What have I done wrong ? This is my code :
// Webservice
@GET("url 1")
Observable<List<Data1>> getData1();
@GET("url 2")
Observable<List<Data2>> getData2();
@GET("url 3")
Observable<List<Data3>> getData3();
//MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//getTextViews
getData();
}
private void getData(){
Retrofit retrofit = Retrofit.Builder()
.baseUrl("apiURL")
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
.client(httpClient.build())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
WebService service = retrofit.create(WebService.class);
Observable.zip(service.getData1(), service.getData2(), service.getData3(), new Function3<List<Data1>, List<Data2>, List<Data3>, MergedResponse>() {
int i;
@Override
public MergedResponse apply(List<Data1> data1, List<Data2> data2, List<Data3> data3) throws Exception {
return new MergedResponse(data1, data2, data3);
}
}).subscribe(new Observer<MergedResponse>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(MergedResponse mergedResponse) {
// dispatch my merged data
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
computeReceivedData();
}
});
}
private void computeReceivedData(){
// List of expressions to compute data and update the view (textview)
...
textView1.setText()
textView2.setText()
...
// Only the first expression textView1.setText() here is called.If I put it at the begining of the method, it stop after executing it
}
retrofit and rxjava2 vresion
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
implementation "com.squareup.retrofit2:adapter-rxjava2:2.9.0"
implementation 'io.reactivex.rxjava2:rxjava:2.2.2'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
Upvotes: 0
Views: 88
Reputation: 71
I think, you are trying to use MainThread to update UI from background thread.
So you have to add below line in your code
.subscribeOn(Schedulers.io()) // will do operation on background thread
.observeOn(AndroidSchedulers.mainThread()) // will notify UI for changes
Ex.
Observable.zip(service.getData1(), service.getData2(), service.getData3(), new Function3<List<Data1>, List<Data2>, List<Data3>, MergedResponse>() {
int i;
@Override
public MergedResponse apply(List<Data1> data1, List<Data2> data2, List<Data3> data3) throws Exception {
return new MergedResponse(data1, data2, data3);
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<MergedResponse>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(MergedResponse mergedResponse) {
// dispatch my merged data
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
computeReceivedData();
}
});
Upvotes: 2
Reputation: 19
Thank you @yousef, I inspected textView.setText() call and found this error :
Unable to evaluate the expression "totalJ1.setText(""value");" : Method threw 'android.view.ViewRootImpl$CalledFromWrongThreadException' exception.
To solved the problem I forced the call to execute in mainThread inside onComplete():
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
computeReceivedData();
}
});
and everything works well.
Upvotes: 0