Получение исключения нулевого объекта при использовании интерфейса - PullRequest
0 голосов
/ 30 мая 2019

Я создал корзину для покупок с помощью 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 голосов
/ 30 мая 2019

Передайте реализацию интерфейса в конструктор 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
}

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

0 голосов
/ 30 мая 2019

Таким образом, вы пытаетесь получить доступ к слушателю внутри 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() {
    ...
    }
}
0 голосов
/ 30 мая 2019

Вам необходимо создать экземпляр updateCartListener, прежде чем использовать его.Сделайте updateCartListener = new WhatverClassThatImplementsYourInterafce () перед его использованием или задайте свой метод для переопределения Default, если вы используете Java 8, используя новый FunctionalInterface в java.util.Function .

0 голосов
/ 30 мая 2019

Полагаю, вы забыли назначить updateCartListener в вашем адаптере.

    SelectionAdapter(selectionItemArrayList, selectionItemsHashMap, totalAmount);

    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;
                        }
                    });
     selectionRecycler.setAdapter(selectionAdapter);
...