Проблемы с функцией zip в rxjava2 - PullRequest
0 голосов
/ 29 января 2020

Кажется, что функция zip ничего не делает. LOG запросов с TAG INSIDE распечатывает наблюдаемые объекты, но является пустым OUTSIDE. В функции zip вызовы LOG ничего не делают. getPosts возвращает список идентификаторов. Я новичок в Android, так что, может быть, я немного больше, чем я могу жевать с Rx java, но, очевидно, это лучшее решение. По сути, getPosts возвращает список идентификаторов, которые я должен использовать для составления дальнейших запросов в getStory. Если есть что-то попроще, я очень хочу это услышать. Спасибо.

MainActivty

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);
}

1 Ответ

1 голос
/ 29 января 2020

Вы создаете список историй, извлекающих наблюдаемые в фоновом режиме, и одновременно пытаетесь использовать список, созданный в главном потоке.

Почему бы просто не составить более getPosts(), как это?

 hackerNewsApi.getPosts()
 .subscribeOn(Schedulers.io())
 .flatMapIterable(posts -> posts)
 .flatMap(post -> hackerNewsApi.getStory(post))
 .toList()
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(allStories -> { /* ... */ }, error -> { /* ... */ });

flatMapIterable развертывает ваш первоначальный список сообщений и toList рекомбинирует их в некотором порядке.

...