Я обновляю свой recyclerview, используя LiveData, как показано ниже:

viewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
viewModel.getPurchaseList().observe(getViewLifecycleOwner(), new Observer<List<ProductsObject>>() {
    @Override
    public void onChanged(@Nullable List<ProductsObject> productsObjects) {
        adapter.submitList(productsObjects);
        //adapter.notifyDataSetChanged();
    }
});

И я использую FloatActionButton, чтобы изменить значение my MutableLiveData, как показано ниже:

FloatingActionButton fab = view.findViewById(R.id.cart_fab);
fab.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        viewModel.setPurchasePrice(0, 101.2);

    }
});

Все данные изменяются, и onChanged вызывается должным образом, но он обновляет мой recyclerview только тогда, когда я включаю adapter.notifyDataSetChanged();

Если я создаю новый ProductsObject внутри fab и Отправить новый список, recyclerview обновляется без вызова adapter.notifyDataSetChanged();, как показано ниже:

FloatingActionButton fab = view.findViewById(R.id.cart_fab);
fab.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //viewModel.setPurchaseAmount(0, 101.2);
        ProductsObject prod = new ProductsObject("6666", 5, 152.2, "new product");
        List<ProductsObject> prodList = new ArrayList<>();
        prodList.add(prod);
        adapter.submitList(prodList);
    }
});

Я признателен, если бы кто-нибудь мог объяснить почему.

Вот мой адаптер:

public class CartFragAdapter extends RecyclerView.Adapter<CartFragAdapter.CartFragViewHolder> {

    private static final String TAG = "debinf PurchaseAdap";

    private static final DiffUtil.ItemCallback<ProductsObject> DIFF_CALLBACK = new DiffUtil.ItemCallback<ProductsObject>() {
        @Override
        public boolean areItemsTheSame(@NonNull ProductsObject oldProduct, @NonNull ProductsObject newProduct) {
            Log.i(TAG, "areItemsTheSame: old is "+oldProduct.getCode()+" ; new is "+newProduct.getCode());
            return oldProduct.getCode().equals(newProduct.getCode());
        }

        @Override
        public boolean areContentsTheSame(@NonNull ProductsObject oldProduct, @NonNull ProductsObject newProduct) {
            Log.i(TAG, "areContentsTheSame: old is "+oldProduct.getPrice()+" ; new is "+newProduct.getPrice());
            return oldProduct.getPrice() == newProduct.getPrice();
        }
    };

    private AsyncListDiffer<ProductsObject> differ = new AsyncListDiffer<ProductsObject>(this, DIFF_CALLBACK);

    @NonNull
    @Override
    public CartFragViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_purchase, parent, false);
        return new CartFragViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull CartFragViewHolder holder, int position) {
        final ProductsObject purchaseList = differ.getCurrentList().get(position);

        holder.mCode.setText(purchaseList.getCode());
        holder.mPrice.setText(String.valueOf(purchaseList.getPrice()));
        holder.mDescription.setText(purchaseList.getDescription());


    }

    @Override
    public int getItemCount() {
        Log.i(TAG, "getItemCount");
        return differ.getCurrentList().size();
    }

    public void submitList(List<ProductsObject> products){
        Log.i(TAG, "submitList: products.size is "+products.size());
        differ.submitList(products);
    }

    public class CartFragViewHolder extends RecyclerView.ViewHolder {

        public TextView mCode, mPrice, mDescription;

        public CartFragViewHolder(@NonNull View itemView) {
            super(itemView);

            mCode = (TextView) itemView.findViewById(R.id.item_productCode);
            mPrice = (TextView) itemView.findViewById(R.id.item_productPrice);
            mDescription = (TextView) itemView.findViewById(R.id.item_productDescription);
        }
    }
}

И вот мой ViewModel:

public class MyViewModel extends ViewModel {

    MutableLiveData<List<ProductsObject>> purchaseList = new MutableLiveData<>();

    public LiveData<List<ProductsObject>> getPurchaseList() {
        return purchaseList;
    }

    public void setPurchasePrice(int position, double price) {
        List<ProductsObject> itemList = purchaseList.getValue();
        if (itemList != null && itemList.get(position) != null) {
            Log.i("debinf ViewModel", "setPurchaseAmount: "+itemList.get(position).getPrice());
            itemList.get(position).setPrice(price);
            purchaseList.postValue(itemList);
        }

    }

}
1
Aliton Oliveira 6 Окт 2019 в 03:25

1 ответ

Лучший ответ

AsyncListDiffer сохраняет только ссылку в списке. Это означает, что если вы отправляете модифицированный список вместо того, чтобы отправлять новый список, AsncListDiffer не сможет обнаруживать никаких различий, потому что предыдущий список, и новый список ссылается на один и тот же список с теми же элементами.

Чтобы исправить это, вам нужно создать новый список и новый элемент. Измените MyViewModel#setPurchasePrice, как показано ниже:

    public void setPurchasePrice(int position, double price) {
        List<ProductsObject> itemList = purchaseList.getValue();
        if (itemList != null && itemList.get(position) != null) {

            List<ProductsObject> newList = new ArrayList<>();

            for (int i = 0; i < itemList.size(); i++) {
                ProductsObject prevProd = itemList.get(i);

                if (i != position) {
                    newList.add(prevProd);
                } else {
                    ProductsObject newProd = new ProductsObject(..., price, ...);
                    newList.add(newProd);
                }
            }
            purchaseList.postValue(newList);
        }

    }
3
Sanlok Lee 7 Окт 2019 в 21:19