If we are working with some complex data that needs to be reused in multiple steps, it often makes sense to create our own custom classes. It is a very lightweight approach and what's even better--it's very explicit.
With custom classes, it is easy to describe the data passed--it will be the name of the class. For example, the user object + accessToken can become UserCredentials and will look like this:
class User {
String userId;
public User(String userId) {
this.userId = userId;
}
}
class UserCredentials {
public final User user;
public final String accessToken;
public UserCredentials(User user, String accessToken) {
this.user = user;
this.accessToken = accessToken;
}
}
This way, the data in later operations can be accessed using fields that are named explicitly by the purpose of the data they are carrying instead of value1 and value2:
Observable.just(new User("1"), new User("2"), new User("3"))
.map(user -> new UserCredentials(user, "accessToken"))
.subscribe(credentials -> log(credentials.user.userId,
credentials.accessToken));
It is worth emphasizing that one should try keeping these objects immutable--once they are created, they should not be modifiable.