При изменении LiveData не вызывается, RecyclerView остается пустым

#android #android-recyclerview #retrofit #adapter #viewmodel

Вопрос:

моя функция OnChanged никогда не вызывается, когда я выполняю запрос GET с помощью Retrofit и LiveData, и мой RecyclerView никогда не обновляется (он остается пустым)! Запрос на получение работает отлично! Кто-нибудь может мне помочь? Большое спасибо!

Это моя функция:

 public void getProductsByBarcode(RecyclerView recyclerView, ProductListAdapter adapter){
    String accessToken = getIntent().getExtras().getString("accessToken");
    EditText insertBarcode = findViewById(R.id.barcodeNumber);
    String barcode = insertBarcode.getText().toString();
    addViewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(
            this.getApplication()).create(ProductsViewModel.class);
    addViewModel.setData(barcode, accessToken);
    addViewModel.getProductsList().observe(this, new Observer<Product>() {
        @Override
        public void onChanged(Product prods) {
            adapter.submitList(addViewModel.getListFood());
            Log.d("lista", "c'è qualcosa nella lista");
            Log.d("lista", prods.getFood().toString());
        }
    });
}
 

Это моя модель просмотра

 public class ProductsViewModel extends AndroidViewModel {

private ProductRepository repository;
private LiveData<Product> productsList;
private String barcode;
private String accessToken;

public ProductsViewModel(Application application) {
    super(application);
    barcode="";
    accessToken="";
    repository = new ProductRepository(application, barcode, accessToken);
    productsList = null;
}

public LiveData<Product> getProductsList(){
    if(productsList==null){
        productsList = new LiveData<Product>() {
            @Override
            public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super Product> observer) {
                super.observe(owner, observer);
            }
        };
    }
    return productsList;
}

public List<Food> getListFood(){
    return this.repository.listResponse;
}

public void setData(String bar, String tok){
    this.accessToken = tok;
    this.barcode = bar;
    repository.setData(bar, tok);
    productsList = repository.getProductsList();
}

public String getSessionToken(){
    return this.repository.sessionToken;
}

/*public void insertProduct(Product product){
   this.repository.insert(product);
}*/
 

}

Это мое хранилище:

 public class ProductRepository {

private ProductDao prodDao;
private MutableLiveData<Product> productsList;
private String baseURL = "/products?barcode=";
private String barcode;
private String accessToken;
public String sessionToken;
public List<Food> listResponse;

ProductRepository (Application app, String iBarcode, String rToken){
    ProductRoomDatabase db = ProductRoomDatabase.getDatabase(app);
    prodDao = db.productDao();
    barcode = iBarcode;
    accessToken = rToken;
    productsList = null;
}

MutableLiveData<Product> getProductsList(){
    GetProductService service = RetrofitClientInstance.getRetrofitInstance().create(GetProductService.class);
    Call<Product> call = service.getAllProducts("Bearer "   accessToken, baseURL barcode);
    call.enqueue(new Callback<Product>(){
        @Override
        public void onResponse(Call<Product> call, Response<Product> response) {
            if(response.isSuccessful()) {
                Log.d("response1", response.toString());
                Log.d("response2", response.body().toString());
                sessionToken = response.body().getToken();
                Log.d("tokenDaGet", sessionToken);
                listResponse = response.body().getFood();
                if(listResponse.size()==0){
                    Log.d("listaProdotti", "nulla");
                }else{
                    Log.d("listaProdotti", listResponse.toString());
                    Log.d("barcode0", listResponse.get(0).getBarcode());
                }
                insertAll(listResponse);
                productsList.setValue(response.body());
            }
        }

        @Override
        public void onFailure(Call<Product> call, Throwable t) {
            Log.e("ERR", call.toString());
            Log.e("tERR", t.getMessage());
            Log.e("t2ERR", t.toString());
            Log.e("RETROFIT", "Richiesta Retrofit fallita, ma è ancora attiva.");
        }
    });

    return productsList;
}

public void setData(String barcode, String tok) {
    this.accessToken = tok;
    this.barcode = barcode;
    prodDao.getProductsList();
}

void insert(Food food){
    ProductRoomDatabase.databaseWriteExecutor.execute(() -> {
        prodDao.insert(food);
    });
}

void insertAll(List<Food> products){
    ProductRoomDatabase.databaseWriteExecutor.execute(() -> {
        prodDao.insertAll(products);
    });
}
 

}

This is my Adapter:

 public class ProductListAdapter extends ListAdapter<Food, ProductViewHolder> {

protected ProductListAdapter(@NonNull FoodDiff diffCallback) {
    super(diffCallback);
}

@NonNull
@Override
public ProductViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    return ProductViewHolder.create(parent);
}

@Override
public void onBindViewHolder(@NonNull ProductViewHolder holder, int position) {
    Food current = getItem(position);
    holder.bind(current.getBarcode());
}

static class FoodDiff extends DiffUtil.ItemCallback<Food> {
    @Override
    public boolean areItemsTheSame(@NonNull Food oldItem, @NonNull Food newItem) {
        return oldItem == newItem;
    }

    @Override
    public boolean areContentsTheSame(@NonNull Food oldItem, @NonNull Food newItem) {
        return oldItem.getBarcode().equals(newItem.getBarcode());
    }
}
 

}

Это моя точка зрения.:

 public class ProductViewHolder extends RecyclerView.ViewHolder {

private TextView prodItemView;

public ProductViewHolder(@NonNull View itemView) {
    super(itemView);
    prodItemView = itemView.findViewById(R.id.productId);
}

public void bind(String text){
    prodItemView.setText(text);
}

static ProductViewHolder create(ViewGroup parent) {
    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.product_item, parent, false);
    return new ProductViewHolder(view);
}
 

}

РЕДАКТИРОВАТЬ: Теперь я изменил LiveData на MutableLiveData и добавил » productsList.setValue(response.body ())»; но у меня ошибка с нулевой ссылкой на объект.

java.lang.Исключение NullPointerException: Попытка вызвать виртуальный метод ‘void androidx.lifecycle.MutableLiveData.setValue(java.lang.Объект)’ по нулевой ссылке на объект

Ответ №1:

Вы не можете получить ответ вне onResponce().вы можете использовать MutableLiveData.

   public void getProductsList(){
    GetProductService service = RetrofitClientInstance.getRetrofitInstance().create(GetProductService.class);
    Call<Product> call = service.getAllProducts("Bearer "   accessToken, baseURL barcode);
    call.enqueue(new Callback<Product>(){
        @Override
        public void onResponse(Call<Product> call, Response<Product> response) {
            if(response.isSuccessful()) {
                Log.d("response1", response.toString());
                Log.d("response2", response.body().toString());
                sessionToken = response.body().getToken();
                Log.d("tokenDaGet", sessionToken);
                listResponse = response.body().getFood();
                if(listResponse.size()==0){
                    Log.d("listaProdotti", "nulla");
                }else{
                    Log.d("listaProdotti", listResponse.toString());
                    Log.d("barcode0", listResponse.get(0).getBarcode());
                }
                insertAll(listResponse);
              //here set value for mutableliveData,observe this from your activity 
              // because return statement will invoked first before get response from 
              // server.
               productsList.setValue(yourData);

            }
        }

        @Override
        public void onFailure(Call<Product> call, Throwable t) {
            Log.e("ERR", call.toString());
            Log.e("tERR", t.getMessage());
            Log.e("t2ERR", t.toString());
            Log.e("RETROFIT", "Richiesta Retrofit fallita, ma è ancora attiva.");
        }
    });

  
}
 

Комментарии:

1. Ваши данные-это ответ.body() ? У меня ошибка с нулевой ссылкой на объект 🙁

2. Да.если вы пытаетесь получить данные от retofit, ответьте на обновление адаптера.

3. Итак, могу ли я устранить эту ошибку? Тело ответа не равно нулю, или я ошибаюсь?

4. Можете ли вы обновить вопрос с помощью обновленного кода