使用接口时获取空对象异常

时间:2019-05-29 23:46:50

标签: android android-recyclerview nullpointerexception

我已经通过recyclerview创建了购物车。每个观看者还具有一个+和-按钮来添加或删除数量。此功能是在适配器中完成的,我必须将更新的总额通知父片段。最后一点是通过接口完成的。问题是,我收到以下错误:

Process: com.ecomm.market, PID: 6630
    java.lang.NullPointerException: Attempt to invoke interface method 'void com.ecomm.market.SelectionAdapter$OnUpdateCartListener.onUpdateCart(int)' on a null object reference
        at com.ecomm.market.SelectionAdapter$ViewHolder$1.onClick(SelectionAdapter.java:103)
        at android.view.View.performClick(View.java:5637)
        at android.view.View$PerformClick.run(View.java:22429)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

所选项目和相应的数量存储在哈希图中,我将其转换为数组以填充回收者视图购物车。这是我的主要片段 MenuFragment 的相关部分的样子:


                // Using the adapter interface to add items to cart and adding up total amount
                menuItemAdapter.setOnAddToCartListener(new MenuItemAdapter.OnAddToCartListener() {
                    @Override
                    public void onAddToCart(final HashMap selectionItemsHashMap) {

                        setupSelectionRecycler(menuView);
                        totalAmount = mapToArray(selectionItemsHashMap);

                            selectionAdapter = new SelectionAdapter(selectionItemArrayList, selectionItemsHashMap, totalAmount);

                        selectionRecycler.setAdapter(selectionAdapter);
                        cartItemsHashmap = selectionItemsHashMap;

                        selectionAdapter.setUpdateCartListener(new SelectionAdapter.OnUpdateCartListener() {
                            @Override
                            public void onUpdateCart(int updatedTotalAmount) {

                                String stringTotalAmount = Integer.toString(updatedTotalAmount);
                                Log.d(TAG, "received total:" +stringTotalAmount);
                                tvTotalAmount.setText("$"+ stringTotalAmount);
                                totalAmount = updatedTotalAmount;
                            }
                        });
                    }
                });
            }

这是我的适配器 SelectionAdapter 的摘录:

public class SelectionAdapter extends RecyclerView.Adapter<SelectionAdapter.ViewHolder> {

    private static final String TAG = SelectionAdapter.class.getSimpleName();

    private ArrayList<SelectionItem> selectionItemArrayList = new ArrayList<>();
    public HashMap<String, Integer> selectionItemsHashMap = new HashMap<String, Integer>();
    public int totalAmount;

    private OnUpdateCartListener updateCartListener;

    public interface OnUpdateCartListener {
        void onUpdateCart(int totalAmount);
    }

    public void setUpdateCartListener(OnUpdateCartListener updateCartListener) {
        this.updateCartListener = updateCartListener;
    }

    public SelectionAdapter(ArrayList<SelectionItem> selectionItemArrayList, HashMap<String, Integer> selectionItemsHashMap, int currentTotalAmount) {
        this.selectionItemArrayList = selectionItemArrayList;
        this.selectionItemsHashMap = selectionItemsHashMap;
        this.totalAmount = currentTotalAmount;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.selection_card, viewGroup, false);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
        viewHolder.tvSelectItem.setText(selectionItemArrayList.get(position).getSelectionName());
        String quantity = Integer.toString(selectionItemArrayList.get(position).getSelectionQuantity());
        viewHolder.tvDishQuantity.setText(quantity);
    }

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


    public class ViewHolder extends RecyclerView.ViewHolder {

        TextView tvSelectItem, tvDishQuantity;
        ImageView addQuantity, subtractQuantity, deleteItem;

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

            tvSelectItem = itemView.findViewById(R.id.dish_selection);
            tvDishQuantity = itemView.findViewById(R.id.dish_quantity);

            addQuantity = itemView.findViewById(R.id.button_add);
            subtractQuantity = itemView.findViewById(R.id.button_subtract);
            deleteItem = itemView.findViewById(R.id.delete_item);

            addQuantity.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                    // Find the name of the menu item
                    int position = getAdapterPosition();
                    String itemName = selectionItemArrayList.get(position).getSelectionName();

                    // Increase quantity
                    int currentQuantity = selectionItemsHashMap.get(itemName);

                    currentQuantity += 1;
                    // Update the hashmap with the new quantity
                    selectionItemsHashMap.put(itemName,currentQuantity);

                    //Update total amount
                    for (Object name: selectionItemsHashMap.keySet()) {
                        String key = (String) name;
                        if (key.equals(selectionItemArrayList.get(position).getSelectionName())) {
                            int eachPrice = Integer.parseInt(selectionItemArrayList.get(position).getSelectionPrice());
                            totalAmount += eachPrice;
                        }
                    }
                    // Display the new quantity
                    String stringCurrentQuantity = Integer.toString(currentQuantity);
                    tvDishQuantity.setText(stringCurrentQuantity);
                    //updateCartListener.onUpdateCart(totalAmount);
                }
            });
}

编辑 要点: -最初装满购物车时,我使用了相同的代码,并且可以正常工作。 -一旦用户返回购物车,然后我必须从包装中重新填充购物车,就会出现问题。一切正常,除非用户直接进入购物车并尝试从那里更改数量。

4 个答案:

答案 0 :(得分:0)

我猜您忘了在适配器中分配updateCartListener了。

答案 1 :(得分:0)

因此,您尝试访问ViewHolder内部的侦听器,这可能是导致崩溃的原因,这是在适配器内部设置OnClickListener的标准方法

@Override
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {        
    viewHolder.tvSelectItem.setText(selectionItemArrayList.get(position).getSelectionName());
    String quantity = Integer.toString(selectionItemArrayList.get(position).getSelectionQuantity());
    viewHolder.tvDishQuantity.setText(quantity);
    viewHolder.addQuantity.setOnClickListener(new View.OnClickListener() {
    ...
    }
}

答案 2 :(得分:0)

在使用updateCartListener之前,需要实例化它。在使用updateCartListener = new WhatverClassThatImplementsYourInterafce()之前,如果要使用the new FunctionalInterface in java.util.Function使用Java 8,请使方法覆盖Default。

答案 3 :(得分:0)

将接口实现传递到Adapter的构造函数中,如下所示:

public SelectionAdapter(ArrayList<SelectionItem> selectionItemArrayList, HashMap<String, Integer> selectionItemsHashMap, int currentTotalAmount,UpdateCartListener updateCartListener ) {
    this.selectionItemArrayList = selectionItemArrayList;
    this.selectionItemsHashMap = selectionItemsHashMap;
    this.totalAmount = currentTotalAmount;
    this.updateCartListener = updateCartListener
}

这将在适配器初始化时提供接口的实现,因此当您将其用于更新购物车时,接口不会为null。