RxJava + Retrofit + Observable цикл запросов

106
26 ноября 2020, 01:00

Имеется база из которой с помощью запросов достаются данные в формате json. Первый запрос возвращает массив объектов, в котором есть поле с внешним ключом к другой таблице, из которой нужно достать объект по данному ключу, а после этого заполнить адаптер. Проблема в том, что я хочу сделать это при помощи rxjava, но возникают ошибки на этапе присвоения значений в адаптере, так как ответ возвращается позже инициализации адаптера.

Класс API

public interface NetworkServiceApi {
    @GET("odata/standard.odata/Document_уатПутевойЛист/")
    Observable<WaybillResponse> getWaybills(@Query("$format") String format, @Query("$filter") String filter, @Query("$expand") String expand);
    @GET("odata/standard.odata/InformationRegister_уатПервоначальныеСведенияТС/")
    Observable<VehicleResponse> getVehicles(@Query("$format") String format, @Query("$filter") String filter, @Query("$expand") String expand);
}

Класс для работы с RXJava

public class RxUtil {
    @SuppressLint("CheckResult")
    public static <S> void networkConsumer(Observable<S> observable, Consumer<S> consumer, @Nullable Consumer<Throwable> errorConsumer) {
        observable
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(consumer, errorConsumer == null ? (Consumer<Throwable>) Throwable::printStackTrace : errorConsumer);
    }
}

Вызов метода из активити и класс самой активити.

   public class MainActivity extends AppCompatActivity implements InteractionListener<Waybill> {
    @BindView(R.id.fab)
    FloatingActionButton fab;
    @BindView(R.id.state)
    TextView state;
    @BindView(R.id.waybill)
    RecyclerView waybill;
    @BindView(R.id.progressBar)
    ProgressBar progressBar;
    private WaybillAdapter waybillAdapter;
    private User user;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        Bundle args = getIntent().getExtras();
        user = (User) (args != null ? args.get("user") : null);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(MainActivity.this, WaybillActivity.class).putExtra("user", user));
            }
        });
        initList();
    }
    @Override
    protected void onResume() {
        super.onResume();
        getWaybills();
    }
    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finish();
    }
    @Override
    public void onItemClick(Waybill item) {
        startActivity(new Intent(this, Main2Activity.class).putExtra("waybill", item));
    }
    private void initList() {
        waybillAdapter = new WaybillAdapter(this, this);
        RecyclerView.LayoutManager layoutManager = new GridLayoutManager(this, 1);
        waybill.setLayoutManager(layoutManager);
        waybill.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        waybill.setAdapter(waybillAdapter);
        waybill.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (dy > 0 && fab.getVisibility() == View.VISIBLE) fab.hide();
                else if (dy < 0 && fab.getVisibility() != View.VISIBLE) fab.show();
            }
        });
    }
    private void getWaybills() {
        String credentials = getSharedPreferences("MyPref", Context.MODE_PRIVATE).getString("credentials", "");
        state.setVisibility(View.GONE);
        progressBar.setVisibility(View.VISIBLE);
        final NetworkServiceApi networkServiceApi = NetworkService.getInstance().getNetworkServiceApi(credentials);
        RxUtil.networkConsumer(networkServiceApi.getWaybills("json", "Ответственный_Key eq " + "guid'" + user.getRefKey() + "'", "*"),
                waybillResponse -> {
                    if (!waybillResponse.isError()) {
                        if (waybillResponse.getWaybills().size() > 0 ) {
                            Log.e("Waybill", "Receive waybills " + waybillResponse.getWaybills().size());
                            for (int i = 0; i < waybillResponse.getWaybills().size(); i++) {
                                final int k = i;
                                RxUtil.networkConsumer(networkServiceApi
                                                .getVehicles("json", "ОсновноеСредство_Key eq " + "guid'" + waybillResponse.getWaybills().get(k).getVehicleKey() + "'", "*"),
                                        vehicleResponse -> {
                                            if (!vehicleResponse.isError()) {
                                                if (vehicleResponse.getVehicles().size() > 0 ) {
                                                    waybillResponse.getWaybills().get(k).setVehicle(vehicleResponse.getVehicles().get(0));
                                                    Log.e("Vehicle", "Init");
                                                    if (k == waybillResponse.getWaybills().size() - 1) {
                                                        Log.e("Activity", "Set");
                                                        waybillAdapter.setWaybills(waybillResponse.getWaybills());
                                                        state.setVisibility(View.GONE);
                                                        progressBar.setVisibility(View.GONE);
                                                    }
                                                }
                                            } else {
                                                Toast.makeText(this, vehicleResponse.getError_messages().get(0), Toast.LENGTH_SHORT).show();
                                            }
                                        }, null);
                            }
                        } else {
                            state.setVisibility(View.VISIBLE);
                            progressBar.setVisibility(View.GONE);
                        }
                    } else {
                        Toast.makeText(this, waybillResponse.getError_messages().get(0), Toast.LENGTH_SHORT).show();
                    }
                }, null);
    }
}

Классы WaybillResponce И VehicleResponce идентичны и возвращают массив объектов Waybill и Vehicle соответственно. Я создал поле Vehicle в классе Waybill для того чтобы работать с 1 объектом.

public class WaybillResponse extends BaseResponse {
    @SerializedName("value")
    private List<Waybill> waybills;
    public List<Waybill> getWaybills() {
        return waybills;
    }
}

Адаптер начинает инициализицию раньше чем данные присвоятся.

Класс адаптера.

public class WaybillAdapter extends RecyclerView.Adapter<WaybillAdapter.ViewHolder> {
    private Context context;
    private List<Waybill> waybills;
    private InteractionListener<Waybill> listener;
    public WaybillAdapter(@NonNull Context context, InteractionListener<Waybill> listener) {
        this.context = context;
        this.listener = listener;
    }
    @NonNull
    @Override
    public WaybillAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        final View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.waybill_item, viewGroup, false);
        return new ViewHolder(view);
    }
    @Override
    public void onBindViewHolder(@NonNull WaybillAdapter.ViewHolder viewHolder, int i) {
        Log.e("Adapter", ""+i);
        final Waybill waybill = getItem(i);
        viewHolder.number.setText(waybill.getNumber());
        viewHolder.date.setText(waybill.getDate());
        viewHolder.vh_number.setText(waybill.getVehicle().getGarageNumber() != null ? waybill.getVehicle().getGarageNumber() : "");
        viewHolder.vh_model.setText(waybill.getVehicle().getModel() != null ? waybill.getVehicle().getModel().getDescription() : "");
        viewHolder.driver.setText(waybill.getFirstDriver().getCode());
        viewHolder.dep_date.setText(waybill.getDepartureDate() != null ? waybill.getDepartureDate() : "");
        viewHolder.speedo_dep.setText(String.valueOf(waybill.getDepartureSpeedo()));
        viewHolder.ret_date.setText(waybill.getReturnDate() != null ? waybill.getReturnDate() : "");
        viewHolder.speedo_ret.setText(String.valueOf(waybill.getReturnSpeedo()));
        if (listener != null)
            viewHolder.view.setOnClickListener(view -> listener.onItemClick(waybill));
    }
    @Override
    public int getItemCount() {
        return waybills == null ? 0 : waybills.size();
    }
    public void setWaybills(List<Waybill> waybills) {
        this.waybills = waybills;
        notifyDataSetChanged();
    }
    private Waybill getItem(int position) {
        int index = position % waybills.size();
        return waybills.get(position);
    }
    class ViewHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.number)
        TextView number;
        @BindView(R.id.date)
        TextView date;
        @BindView(R.id.vh_number)
        TextView vh_number;
        @BindView(R.id.vh_model)
        TextView vh_model;
        @BindView(R.id.driver)
        TextView driver;
        @BindView(R.id.dep_date)
        TextView dep_date;
        @BindView(R.id.speedo_dep)
        TextView speedo_dep;
        @BindView(R.id.ret_date)
        TextView ret_date;
        @BindView(R.id.speedo_ret)
        TextView speedo_ret;
        @BindView(R.id.status)
        TextView status;
        @BindView(R.id.status_route)
        TextView status_route;
        View view;
        ViewHolder(@NonNull View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
            this.view = itemView;
        }
        public Context getContext() {
            return view.getContext();
        }
    }
}

Ошибка - в момент вызова метода getGarageNumber(): переменная является null и происходит ошибка приложения. viewHolder.vh_number.setText(waybill.getVehicle().getGarageNumber() != null ? waybill.getVehicle().getGarageNumber() : "");

READ ALSO
ajax.data form.serialize + myaction

ajax.data form.serialize + myaction

Может вопрос глупый, но прошу помочьне могу найти решение

96
Повторные запросы axios

Повторные запросы axios

axios (post, timeout: 1500) запрос из vue-приложения пытается получить данные с серверасервер не доступен (отключил специально)

89
Обертки для DOM и обработчики событий [дубликат]

Обертки для DOM и обработчики событий [дубликат]

Изучаю чистый JS, хочу добавить методы и свойства для моих DOM элементовВ интернетах сказали, что напрямую записывать методы и свойства в DOM-элементы...

95
Как подключить внешний javascript к форме?

Как подключить внешний javascript к форме?

Каким образом можно подключить внешний javascript файл к форме?

129