#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. Можете ли вы обновить вопрос с помощью обновленного кода