I'm trying load posts from blog. I use mosby + retrofit + rxjava.
public class PostRepository implements IPostRepository {
private Api api;
private long last_id = 0;
private Single<List<Post>> postList;
public PostRepository(Api api) {
this.api = api;
}
@Override
public Single<List<Post>> getList() {
this.load();
return postList;
}
private void load() {
Single<List<Post>> tmp;
Log.d(Configuration.DEBUG_TAG, "Loading " + last_id);
tmp = api.getPostList(last_id)
.map(posts -> {
ArrayList<Post> postList = new ArrayList<>();
for (PostResponse post : posts) {
if (last_id == 0 || last_id > post.id) {
last_id = post.id;
}
postList.add(new Post(
post.id,
post.thumb,
post.created_at,
post.title
));
}
return postList;
});
if (postList == null) {
postList = tmp;
} else {
postList.mergeWith(tmp);
}
}
@Override
public Single<Post> getDetail(long id) {
return api.getPost(id)
.map(postResponse -> new Post(
postResponse.id,
postResponse.thumb,
postResponse.created_at,
postResponse.title,
postResponse.body
));
}
}
and api
public interface Api {
@GET("posts")
Single<PostListResponse> getPostList(@Query("last_id") long last_id);
@GET("post/{id}")
Single<PostResponse> getPost(@Path("id") long id);
}
First query to website is ok. https://site/posts?last_id=0
But second run function getList does not work. I always get the same get query with last_id = 0, but line in console write
D/App: Loading 1416
D/App: 1416
D/OkHttp: --> GET https://site/posts?last_id=0 http/1.1
if i write
tmp = api.getPostList(1000)
then i get true query string https://site/posts?last_id=1000
Update I rewrite code repository.
public class PostRepository implements IPostRepository {
private Api api;
private long last_id = 0;
private List<Post> postList = new ArrayList<>();
private Observable<List<Post>> o;
public PostRepository(Api api) {
this.api = api;
}
@Override
public Single<List<Post>> getList() {
return load();
}
private Single<List<Post>> load() {
return api.getPostList(last_id)
.map(posts -> {
for (PostResponse post : posts) {
if (last_id == 0 || last_id > post.id) {
last_id = post.id;
}
postList.add(new Post(
post.id,
post.thumb,
post.created_at,
post.title
));
}
return postList;
});
}
@Override
public Single<Post> getDetail(long id) {
return api.getPost(id)
.map(postResponse -> new Post(
postResponse.id,
postResponse.thumb,
postResponse.created_at,
postResponse.title,
postResponse.body
));
}
}
It's work
Your problem lies in this code fragment:
if (postList == null) {
postList = tmp;
} else {
postList.mergeWith(tmp); // here
}
Operators on observables are performing immutable operations, which means that it always returns new stream which is a modified version of the previous one. That means, that when you apply mergeWith
operator, the result of this is thrown away as you are not storing it anywhere. The most easy to fix this is to replace the old postList variable with the new stream.
However, this is not optimal way of doing this. You should have a look on Subjects and emit new values within the old stream as your current solution will not affect previous subscribers as they have subscribed to a different stream