0

Есть список имен, по которому нажимаю. После чего должен сохраняться нажатый элемент, который я использую в другом фрагменте.

Список загружается, но при кликах на имена выбивает следующую ошибку:

java.lang.NullPointerException: Attempt to invoke interface method 'void com.vm.sai.adapters.PersonAdapter$OnRecItemClickListener.onRecItemClick(int)' on a null object reference
at com.vm.sai.adapters.PersonAdapter$PersonViewHolder.onClick(PersonAdapter.java:57)

Код адаптера:

public class PersonAdapter extends RecyclerView.Adapter<PersonAdapter.PersonViewHolder> {
    List<String> perscategories;
    OnRecItemClickListener onRecItemClickListener;

    public PersonAdapter(List<String> perscategories, OnRecItemClickListener onRecItemClickListener) {
        this.onRecItemClickListener = onRecItemClickListener;
        this.perscategories = perscategories;
    }

    public interface OnRecItemClickListener {
        void onRecItemClick(int position);
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
    }


    public static class PersonViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private TextView personName;
        private int position;
        private OnRecItemClickListener onRecItemClickListener;

        PersonViewHolder(View itemView, OnRecItemClickListener onRecItemClickListener) {
            super(itemView);
            personName = (TextView) itemView.findViewById(R.id.persname);
            personName.setOnClickListener(this);
        }

        public void bind(String text, int position) {
            this.position = position;
            personName.setText(text);
        }

        @Override
        public void onClick(View v) {
            onRecItemClickListener.onRecItemClick(position);
        }
    }

    @Override
    public PersonViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.person_list_item, viewGroup, false);
        return new PersonViewHolder(v, onRecItemClickListener);
    }

    @Override
    public void onBindViewHolder(PersonViewHolder personViewHolder, final int position) {
        personViewHolder.bind(perscategories.get(position), position);
    }

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

Фрагмент в котором создаю экземпляр класса:

private void initializeAdapter() {
    PersonAdapter personAdapter = new PersonAdapter(personCategories, new PersonAdapter.OnRecItemClickListener() {
        @Override
        public void onRecItemClick(int position) {
            saveFavorites(position);
        }
    });
    recyclerView.setAdapter(personAdapter);
}
Inkognito
  • 911
  • 1
    добавьте в вопрос код, который присваивает значение onRecItemClickListener = ... –  Jan 03 '17 at 17:37
  • У вас onRecItemClickListener null. По приведённому вами коду более ничего сказать нельзя. Вы просто где-то забыли инициализировать эту переменную. Т.е. дело в вашей невнимательности – ЮрийСПб Jan 03 '17 at 18:19
  • @ЮрийСПб обновил вопрос, с учётом ответа ниже. – Inkognito Jan 03 '17 at 19:51

2 Answers2

1

Данное исключение говорит о том, что Вы пытаетесь вызвать метод на объекте, который проинициализирован значением null.

Вы пытаетесь вызвать метод onRecItemClick(...) на объекте onRecItemClickListener, в котором находится null.

Решением данной проблемы будет инициализация объекта onRecItemClickListener (до его использования).

post_zeew
  • 21,983
  • проинициализировал интерфейс onRecItemClickListener раньше метода onRecItemClick, но увы ошибка по прежнему такая же – Inkognito Jan 03 '17 at 19:50
  • @Inkognito, Покажите строку, в который Вы создаете экземпляр класса PersonAdapter. – post_zeew Jan 03 '17 at 19:58
  • обновил вопрос, взгляните пожалуйста. – Inkognito Jan 03 '17 at 20:03
  • @Inkognito, Инициализировали Вы, да не то что нужно. После клика происходит обращения к полю onRecItemClickListener класса PersonViewHolder, которое не инициализировано. Вы передаете листенер в конструктор класса PersonViewHolder, но в конструкторе Вы нигде его не используете. Сделайте присваивание там. А вообще, мне непонятно, зачем у Вас листенер является как полем адаптера, так и полем вьюхолдера. – post_zeew Jan 03 '17 at 20:09
  • в PersonViewHolder(View itemView, OnRecItemClickListener onRecItemClickListener) { сделать присвоение? + если я его удалю оттуда, то в onCreateViewHolder тоже придётся его убрать. – Inkognito Jan 03 '17 at 20:42
  • 1
    @Inkognito, Да. – post_zeew Jan 03 '17 at 20:51
1

Вы передали слушатель в холдер, но не присвоили его переменной холдера.

Можно по разному решить

  1. Таки присвоить значение из аргумента конструктора холдера полю холдера.
  2. Убрать слушатель из холдера и из его конструктора, сделать класс холдера НЕстатическим и тогда будет использоваться слушатель из поля адаптера, а не холдера.
  • 2-ой вариант не очень понятен на словах( c 1-м разобрался – Inkognito Jan 03 '17 at 20:53
  • 1
    У вас слушатель является как полем класса адаптера так и холдера. Если сделать холдер НЕстатическим, то он будет иметь доступ ко всем полям адаптера как его внутренний класс. В таком случае передавать в него слушатель будет не нужно – ЮрийСПб Jan 03 '17 at 21:11