rxjava2 中 zip 函数的问题
Problems with zip function in rxjava2
zip 函数似乎不执行 anything.The 带有 TAG INSIDE 的请求日志打印出可观察对象但为空 OUTSIDE.In zip 函数 LOG 调用不执行任何操作。 getPosts returns id 列表。
我是 Android 的初学者,所以也许我对 Rxjava 的理解还不够,但显然这是我最好的 solution.Essentially、getPosts
returns id 列表应该用于在 getStory
中编写进一步的请求。如果有更简单的我很想听到 it.Thanks。
主要活动
package com.example.hackernews;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import static java.lang.Math.min;
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private List<DataResponse> dataResponses;
private Observable<List<Integer>> ids;
private List<Observable<DataResponse>> requests = new ArrayList<>();
@SuppressLint("CheckResult")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// mRecyclerView = findViewById(R.id.recyclerView);
// mRecyclerView.setHasFixedSize(true);
// mLayoutManager = new LinearLayoutManager(getApplicationContext());
// mRecyclerView.setLayoutManager(mLayoutManager);
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://hacker-news.firebaseio.com/v0/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(client)
.build();
HackerNewsApi hackerNewsApi = retrofit.create(HackerNewsApi.class);
ids = hackerNewsApi.getPosts();
ids.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(id -> {
for (Integer i : id) {
requests.add(hackerNewsApi.getStory(i));
}
Log.e("onSubscribe", "INSIDE " + requests);
}, Throwable::printStackTrace);
Log.e("onSubscribe", "OUTSIDE " + requests);
Observable.zip(
requests,
new Function<Object[], Object>() {
@Override
public Object apply(Object[] objects) throws Exception {
// Objects[] is an array of combined results of completed requests
Log.e("onSubscribe", "YOUR OBJECTS ARE HERE: " + objects);
// do something with those results and emit new event
return new Object();
}
})
// After all requests had been performed the next observer will receive the Object, returned from Function
.subscribe(
// Will be triggered if all requests will end successfully (4xx and 5xx also are successful requests too)
new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
//Do something on successful completion of all requests
Log.e("onSubscribe", "YOUR OBJECTS ARE HERE: " + o);
}
},
// Will be triggered if any error during requests will happen
new Consumer<Throwable>() {
@Override
public void accept(Throwable e) throws Exception {
//Do something on error completion of requests
}
}
);
// mRecyclerView = findViewById(R.id.recyclerView);
// mRecyclerView.setHasFixedSize(true);
// mLayoutManager = new LinearLayoutManager(this);
// Log.e("onSubscribe", "YOUR DATA IS HERE: " + dataResponses);
// mAdapter = new ExampleAdapter(dataResponses);
//
//
// mRecyclerView.setLayoutManager(mLayoutManager);
// mRecyclerView.setAdapter(mAdapter);
}
}
HackerNewsApi
package com.example.hackernews;
import java.util.List;
import io.reactivex.Observable;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
public interface HackerNewsApi {
@GET("askstories.json?print=pretty")
Observable<List<Integer>> getPosts();
@GET("item/{id}.json?print=pretty")
Observable<DataResponse> getStory(@Path("id") Integer id);
}
您创建了一个故事列表,在后台检索可观察对象,并同时尝试使用在主线程上构建的列表。
为什么不像这样简单地合成 getPosts()
?
hackerNewsApi.getPosts()
.subscribeOn(Schedulers.io())
.flatMapIterable(posts -> posts)
.flatMap(post -> hackerNewsApi.getStory(post))
.toList()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(allStories -> { /* ... */ }, error -> { /* ... */ });
flatMapIterable
展开您的初始帖子列表,然后 toList
按某种顺序重新组合它们。
zip 函数似乎不执行 anything.The 带有 TAG INSIDE 的请求日志打印出可观察对象但为空 OUTSIDE.In zip 函数 LOG 调用不执行任何操作。 getPosts returns id 列表。
我是 Android 的初学者,所以也许我对 Rxjava 的理解还不够,但显然这是我最好的 solution.Essentially、getPosts
returns id 列表应该用于在 getStory
中编写进一步的请求。如果有更简单的我很想听到 it.Thanks。
主要活动
package com.example.hackernews;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import static java.lang.Math.min;
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private List<DataResponse> dataResponses;
private Observable<List<Integer>> ids;
private List<Observable<DataResponse>> requests = new ArrayList<>();
@SuppressLint("CheckResult")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// mRecyclerView = findViewById(R.id.recyclerView);
// mRecyclerView.setHasFixedSize(true);
// mLayoutManager = new LinearLayoutManager(getApplicationContext());
// mRecyclerView.setLayoutManager(mLayoutManager);
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://hacker-news.firebaseio.com/v0/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(client)
.build();
HackerNewsApi hackerNewsApi = retrofit.create(HackerNewsApi.class);
ids = hackerNewsApi.getPosts();
ids.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(id -> {
for (Integer i : id) {
requests.add(hackerNewsApi.getStory(i));
}
Log.e("onSubscribe", "INSIDE " + requests);
}, Throwable::printStackTrace);
Log.e("onSubscribe", "OUTSIDE " + requests);
Observable.zip(
requests,
new Function<Object[], Object>() {
@Override
public Object apply(Object[] objects) throws Exception {
// Objects[] is an array of combined results of completed requests
Log.e("onSubscribe", "YOUR OBJECTS ARE HERE: " + objects);
// do something with those results and emit new event
return new Object();
}
})
// After all requests had been performed the next observer will receive the Object, returned from Function
.subscribe(
// Will be triggered if all requests will end successfully (4xx and 5xx also are successful requests too)
new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
//Do something on successful completion of all requests
Log.e("onSubscribe", "YOUR OBJECTS ARE HERE: " + o);
}
},
// Will be triggered if any error during requests will happen
new Consumer<Throwable>() {
@Override
public void accept(Throwable e) throws Exception {
//Do something on error completion of requests
}
}
);
// mRecyclerView = findViewById(R.id.recyclerView);
// mRecyclerView.setHasFixedSize(true);
// mLayoutManager = new LinearLayoutManager(this);
// Log.e("onSubscribe", "YOUR DATA IS HERE: " + dataResponses);
// mAdapter = new ExampleAdapter(dataResponses);
//
//
// mRecyclerView.setLayoutManager(mLayoutManager);
// mRecyclerView.setAdapter(mAdapter);
}
}
HackerNewsApi
package com.example.hackernews;
import java.util.List;
import io.reactivex.Observable;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
public interface HackerNewsApi {
@GET("askstories.json?print=pretty")
Observable<List<Integer>> getPosts();
@GET("item/{id}.json?print=pretty")
Observable<DataResponse> getStory(@Path("id") Integer id);
}
您创建了一个故事列表,在后台检索可观察对象,并同时尝试使用在主线程上构建的列表。
为什么不像这样简单地合成 getPosts()
?
hackerNewsApi.getPosts()
.subscribeOn(Schedulers.io())
.flatMapIterable(posts -> posts)
.flatMap(post -> hackerNewsApi.getStory(post))
.toList()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(allStories -> { /* ... */ }, error -> { /* ... */ });
flatMapIterable
展开您的初始帖子列表,然后 toList
按某种顺序重新组合它们。