onChanged LiveData 未调用,RecyclerView 保持为空

Posted

技术标签:

【中文标题】onChanged LiveData 未调用,RecyclerView 保持为空【英文标题】:onChanged LiveData not called, RecyclerView remains empty 【发布时间】:2021-08-10 22:03:03 【问题描述】:

当我使用 Retrofit 和 LiveData 执行 GET 请求时,永远不会调用我的 onChanged 函数,并且我的 RecyclerView 永远不会更新(它仍然为空)! GET 请求完美运行! 谁能帮我? 非常感谢!

这是我的功能:

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

这是我的适配器:

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

这是我的 ViewHolder:

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.Object)”

【问题讨论】:

【参考方案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.");
        
    );

  

【讨论】:

yourData 是 response.body() 吗?我有一个空对象引用错误:( 是的。如果您尝试从 retofit 响应中获取数据以更新适配器。 那么我可以解决这个错误吗?响应正文不为空还是我错了? 你能用更新的代码更新问题吗

以上是关于onChanged LiveData 未调用,RecyclerView 保持为空的主要内容,如果未能解决你的问题,请参考以下文章

仅第一次调用 LiveData onChanged 方法

Room:来自 Dao 的 LiveData 将在每次更新时触发 Observer.onChanged,即使 LiveData 值没有变化

未调用 LiveData 观察者

LiveData 观察()未调用

livedata数据倒灌与粘性事件

Android Room LiveData观察器未更新