I am trying to chain network requests using RxJava in Android, and then retry when it fails. I've been looking over StackOverflow on how to do this without getting into Callback hell that comes with using vanilla Android and Retrofit alone. I can do this all in a procedure, in an asynchronous task like this (below are the steps that I need to make) to log in.
- Login a user with username/password
- Request SSO token if that response is successful
- Call a launch service with that sso token
I've been doing this in an AsyncTask which worked only when signing in. However, the SSO token expires while the application is in use, so I need to make the request every time I see that it expires.
The code for the AsyncTask looks like this:
private class LoginUserTask extends AsyncTask<Void, Void, Void> {
private final String LOG_TAG = LoginUserTask.class.getSimpleName();
@Override
protected Void doInBackground(Void... params) {
OkHttpClient httpClient = ((TribeSocial) getApplication()).getHttpClient();
// Login User
GroupDockService groupDockLoginService =
GroupDockServiceGenerator
.createService(GroupDockService.class,
httpClient, GroupDockUser.class, new GroupDockUserDeserializer());
GroupDockUser groupDockUser = groupDockLoginService.loginUser("Tribe", username, password);
Utility.saveAccountSubdomain(mContext, groupDockUser.getGroupDockSubdomain().getSubdomain());
// Get Sso Token
GroupDockService groupDockService = GroupDockServiceGenerator
.createService(GroupDockService.class, httpClient);
GroupDockSsoResponse ssoResponse =
groupDockService.getSsoToken(Utility.getAccountSubdomain(mContext), true);
Utility.saveSsoToken(mContext, ssoResponse.getSsoToken());
// Sign in user into Tribe service
TribeSocialService tribeSocialLaunchService =
TribeServiceGenerator.createService(TribeSocialService.class,
httpClient, new LenientGsonConverter(new Gson()));
tribeSocialLaunchService.launch(Utility.getSsoToken(mContext));
// Get User id and save it to SharedPreferences
TribeSocialService tribeSocialWhoAmIService =
TribeServiceGenerator.createService(TribeSocialService.class, httpClient,
User.class, new WhoAmIDeserializer());
User tribeUser = tribeSocialWhoAmIService.whoami();
Utility.saveUserId(mContext, tribeUser.getId());
return null;
}
@Override
protected void onPostExecute(Void v) {
Utility.launchMainActivity(mContext);
}
}
My attempt at making this work with RxJava is something like
GroupDockService groupDockLoginService =
GroupDockServiceGenerator
.createService(GroupDockService.class,
mHttpClient, GroupDockUser.class, new GroupDockUserDeserializer());
groupDockLoginService
.loginUserRx("Tribe", username, password)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<GroupDockUser>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.e(LOG_TAG, "I have errored out: " + e.getMessage());
Toast.makeText(mContext,
getString(R.string.username_and_or_password_is_incorrect),
Toast.LENGTH_SHORT).show();
}
@Override
public void onNext(GroupDockUser groupDockUser) {
Utility.saveUsernamePassword(mContext, username, password);
new LoginUserTask().execute();
}
});
In that code, I need to do the following
- When loginUserRx succeeds, I need to save the username and password into SavedPreferences
- I then need to make a network request to get the sso token
- After that, I need to make the third and final network request to launch.
The code right now simply makes a call to login the user, and once that succeeds, kicks off the async task. Ideally, I would like to chain the requests all together in that one request. I've been experimenting with flatmap, map, and etc., and can't figure out how to chain these calls as I stepped out above.
Can anyone shine some light on this? Thanks.
retry? I don't see how map or flatmap help do what you want - OneCricketeer