首页 > 解决方案 > 通过单击项目的按钮更新 RecyclerView 项目

问题描述

我有一个 RecyclerView 显示有关某些产品的详细信息。每个 recyclerview 项目都包含详细信息,例如产品名称、库存数量和售价。还有一个用于销售产品的按钮。

当我点击按钮时,会打开一个alertDialog询问要出售的数量,在出售一定数量后,数据库中的库存会按预期更改,但在alertDialog关闭后recyclerview项目没有更新。如果我去其他活动并回来,recyclerview 项目将更新,但我希望它在 alertDialog 关闭后立即更新。

我检查了其他类似的问题,但我无法解决。最常见的答案是放

adapter.notifyDatasetChanged()

在创建 recyclerview 对象的活动中......但是在哪里?因为接收数量的警报对话框的代码在 ViewHolder 类中。如何从活动类中调用上述内容?

下面是我的活动代码,它有 recyclerview。

public class Inventory extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    RecyclerView recyclerInventory;
    RecyclerView.LayoutManager layoutManager;
    List<Product> inventory = new ArrayList<>();
    InventoryAdapter adapter;
    TextView emptyView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_inventory);
        Toolbar toolbar = findViewById(R.id.toolbar);
        toolbar.setTitle(R.string.title_activity_inventory);
        setSupportActionBar(toolbar);
        FloatingActionButton fab = findViewById(R.id.add_item);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(Inventory.this, AddItem.class));
            }
        });
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        NavigationView navigationView = findViewById(R.id.nav_view);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.inventory_navigation_drawer_open, R.string.inventory_navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();
        navigationView.setNavigationItemSelectedListener(this);

        recyclerInventory = (RecyclerView) findViewById(R.id.recycler_home);
        emptyView = (TextView) findViewById(R.id.empty_image);

        layoutManager = new GridLayoutManager(this, 1, RecyclerView.VERTICAL, false);
        recyclerInventory.setLayoutManager(layoutManager);

        loadProductList();

        //InventoryAdapter adapter = new InventoryAdapter(new MSDatabase(this).getProducts(), this);
    }

    private void loadProductList() {
        inventory = new MSDatabase(this).getProducts();

            adapter = new InventoryAdapter(inventory, this,new ItemClickListener() {
                @Override
                public void onItemClick(int position) {

                }
            });
            adapter.notifyDataSetChanged();
            recyclerInventory.setAdapter(adapter);

            if(adapter.getItemCount() > 0) {
                recyclerInventory.setVisibility(View.VISIBLE);
                emptyView.setVisibility(View.GONE);
            }
            else {
                recyclerInventory.setVisibility(View.GONE);
                emptyView.setVisibility(View.VISIBLE);
            }
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.inventory, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Inventory/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

还有我的 InventoryAdapter 和 ViewHolder 类

class InventoryViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,
View.OnCreateContextMenuListener {
    TextView productName, inStock, sellingPrice;
    FButton sellButton, purchaseButton, deleteButton;
    private WeakReference<ItemClickListener> listenerRef;
    EditText sellQuantity;
    List<Product> inventory = new ArrayList<>();
    InventoryAdapter adapter;


    public InventoryViewHolder(View prodView) {
        super(prodView);

        productName = (TextView) prodView.findViewById(R.id.product_name);
        inStock = (TextView) prodView.findViewById(R.id.product_in_stock);
        sellingPrice = (TextView) prodView.findViewById(R.id.product_sellingprice);
        sellButton = (FButton) prodView.findViewById(R.id.btn_sell);
        purchaseButton = (FButton) prodView.findViewById(R.id.btn_purchase);
        deleteButton = (FButton) prodView.findViewById(R.id.btn_delete);

        sellButton.setOnClickListener(this);
        purchaseButton.setOnClickListener(this);
        deleteButton.setOnClickListener(this);

        prodView.setOnCreateContextMenuListener(this);
    }

    @Override
    public void onClick(View v) {

        if(v.getId() == sellButton.getId())
        {
            AlertDialog.Builder builder1 = new AlertDialog.Builder(v.getContext());
            builder1.setMessage("Select quantity");
            builder1.setCancelable(true);
            Context context = v.getContext();
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View sell_dialog_layout = inflater.inflate(R.layout.sell_product_layout,null);
            builder1.setView(sell_dialog_layout);
            builder1.setIcon(R.drawable.ic_warning_black_24dp);
            sellQuantity = (EditText) sell_dialog_layout.findViewById(R.id.elegent_number_button);
                    builder1.setPositiveButton(
                            "OK",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id)
                                {
                                    //Toast.makeText(v.getContext(),"Qty:" + sellQuantity.getText().toString() + " sell position:" + String.valueOf(getAdapterPosition()+1) , Toast.LENGTH_SHORT).show();
                                    new MSDatabase(v.getContext()).sellProduct(getAdapterPosition(), Double.parseDouble(sellQuantity.getText().toString())), v.getContext());

                                }
                            });

                    builder1.setNegativeButton(
                            "Cancel",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {
                                    dialog.cancel();

                                }
                            });

                    AlertDialog alert11 = builder1.create();
                    alert11.show();
        }
        else if(v.getId() == purchaseButton.getId())
        {
            //Toast.makeText(v.getContext(), "purchase position:" + String.valueOf(getAdapterPosition()+1), Toast.LENGTH_SHORT).show();
// Yet to be done
            AlertDialog.Builder builder1 = new AlertDialog.Builder(v.getContext());
            builder1.setMessage("Select quantity");
            builder1.setCancelable(true);
            Context context = v.getContext();
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View sell_dialog_layout = inflater.inflate(R.layout.sell_product_layout,null);
            builder1.setView(sell_dialog_layout);
            builder1.setIcon(R.drawable.ic_warning_black_24dp);
            sellQuantity = (EditText) sell_dialog_layout.findViewById(R.id.elegent_number_button);
            builder1.setPositiveButton(
                    "OK",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id)
                        {
                            Toast.makeText(v.getContext(),"Qty:" + sellQuantity.getText().toString() + " sell position:" + String.valueOf(getAdapterPosition()+1) , Toast.LENGTH_SHORT).show();
                        }
                    });

            builder1.setNegativeButton(
                    "Cancel",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    });

            AlertDialog alert11 = builder1.create();
            alert11.show();


        }
        else if(v.getId() == deleteButton.getId())
        {
            Toast.makeText(v.getContext(), "delete position:" + String.valueOf(getAdapterPosition()+1), Toast.LENGTH_SHORT).show();
// Yet to be done
        }

        try {
            ItemClickListener checknull = listenerRef.get();
        }

       catch (Exception e){
            Log.v("InventoryViewHolder: ","WeakReference.get() is null");
        }
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        menu.setHeaderTitle(R.string.select_an_action);
        menu.add(0, 0, getAdapterPosition(), Common.UPDATE);
        menu.add(0,0,getAdapterPosition(),Common.DELETE);
    }
}

    public class InventoryAdapter extends RecyclerView.Adapter<InventoryViewHolder> {

        private List<Product> listData = new ArrayList<>();
        private Context context;
        private ItemClickListener listener;

        public InventoryAdapter(List<Product> listData, Context context, ItemClickListener listener) {
            this.listData = listData;
            this.context = context;
            this.listener = listener;
        }

        @NonNull
        @Override
        public InventoryViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {

            View prodView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.inventory_product_layout, viewGroup, false);
            return new InventoryViewHolder(prodView);
        }

        @Override
        public void onBindViewHolder(@NonNull final InventoryViewHolder inventoryViewHolder, int i) {

            inventoryViewHolder.productName.setText(listData.get(i).getProductName());
            inventoryViewHolder.inStock.setText(String.valueOf(listData.get(i).getProductInStock()));
            inventoryViewHolder.sellingPrice.setText(String.valueOf(listData.get(i).getProductSellingPrice()));
        }

        @Override
        public int getItemCount() {
            return listData.size();
        }

        public void setData(List<Product> data){
            this.listData = data;
            notifyDataSetChanged();
            // where this.data is the recyclerView's dataset you are
            // setting in adapter=new Adapter(this,db.getData());
        }
    }

在数据库类中销售产品的方法如下。

    public void sellProduct(int rowId, double quantityChange, Context context) {
        SQLiteDatabase db = getReadableDatabase();

        Product selectedProduct = getSelectedProduct(String.valueOf(rowId));
        Log.v("Check name: ", selectedProduct.getProductName());
        //Log.v("Check inStock: ", String.valueOf(selectedProduct.getProductInStock()));
        ContentValues cv = new ContentValues();
        cv.put("ProductName", selectedProduct.getProductName());
        cv.put("InStock", selectedProduct.getProductInStock() - quantityChange);
        cv.put("CostPrice", selectedProduct.getProductCostPrice());
        cv.put("SellingPrice", selectedProduct.getProductSellingPrice());
        cv.put("Description", selectedProduct.getProductDescription());
        cv.put("PurchaseDate", selectedProduct.getDateOfPurchase());
        cv.put("ExpiryDate", selectedProduct.getDateOfExpiry());
        cv.put("GstRate", selectedProduct.getGstRate());
        cv.put("GstAmount", selectedProduct.getGstAmount());

        int result = db.update("Inventory", cv, "rowid = ?", new String[]{String.valueOf(rowId+1)});
        if(result > 0) {
            Toast.makeText( context, "Sold successfully !", Toast.LENGTH_LONG).show();
        }
        else {
            Toast.makeText( context, "Try again !", Toast.LENGTH_LONG).show();
        }
    }

我承认有类似的问题,但答案根本不适合我,请帮忙。

更新:

我在 onBindViewHolder 中使用了侦听器

@Override
        public void onBindViewHolder(@NonNull final InventoryViewHolder inventoryViewHolder, int i) {

            inventoryViewHolder.productName.setText(listData.get(i).getProductName());
            inventoryViewHolder.inStock.setText(String.valueOf(listData.get(i).getProductInStock()));
            inventoryViewHolder.sellingPrice.setText(String.valueOf(listData.get(i).getProductSellingPrice()));

            inventoryViewHolder.sellButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    AlertDialog.Builder builder1 = new AlertDialog.Builder(v.getContext());
                    builder1.setMessage("Select quantity");
                    builder1.setCancelable(true);
                    Context context = v.getContext();
                    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    View sell_dialog_layout = inflater.inflate(R.layout.sell_product_layout,null);
                    builder1.setView(sell_dialog_layout);
                    builder1.setIcon(R.drawable.ic_warning_black_24dp);
                    sellQuantity = (EditText) sell_dialog_layout.findViewById(R.id.elegent_number_button);
                    builder1.setPositiveButton(
                            "OK",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id)
                                {
                                    //Toast.makeText(v.getContext(),"Qty:" + sellQuantity.getText().toString() + " sell position:" + String.valueOf(getAdapterPosition()+1) , Toast.LENGTH_SHORT).show();
                                    new MSDatabase(v.getContext()).sellProduct(i, Double.parseDouble(sellQuantity.getText().toString())));
                                    notifyItemChanged(i);
                                    Log.v("Position: ", String.valueOf(i));
                                }
                            });

                    builder1.setNegativeButton(
                            "Cancel",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {
                                    dialog.cancel();

                                }
                            });

                    AlertDialog alert11 = builder1.create();
                    alert11.show();


                }
            });
        }

标签: androidandroid-recyclerview

解决方案


如果需要更新单击的项目,您可以使用notifyItemChanged()仅更新一个视图而不是重建所有列表,或者notifyItemRemoved()如果项目已从列表中删除。

因此,如果您需要更新项目值并在警报后仅重建此项目,您可以尝试在对话框中插入类似的内容(下面提供的描述):

builder1.setPositiveButton(
    "OK",
    new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
            ExampleItem item = list.get(holder.getAdapterPosition());
            notifyItemChanged(holder.getAdapterPosition());
            Toast.makeText(v.getContext(), "Item number: " + holder.getAdapterPosition(), Toast.LENGTH_SHORT).show();

        }
    });
  • list- 是你的清单,那个清单在RecyclerView.
  • item- 您单击的位置的元素。
  • holder.getAdapterPosition()- 单击的位置,您可以将所有更改应用于RecyclerView元素或list借助它。
  • notifyItemChanged(holder.getAdapterPosition());- 您通知RecyclerView此项目已更改,需要重新绘制。

推荐阅读