Получение исключения Null Pointer при настройке прослушивателя щелчка элемента recycler

Я много искал и не нашел решения для своей проблемы. Я создал интерфейс для обработки прослушивателей кликов по определенному элементу в представлении ресайклера. Logcat показывает, что ошибка произошла при настройке прослушивателя в maiactivity.

вот мой файл MainActivity.java

package com.example.mynotes;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.util.List;


public class MainActivity extends AppCompatActivity implements NoteAdapter.OnItemClickListener {
    public static final int ADD_NOTE_REQUEST = 1;
    public static final int EDIT_NOTE_REQUEST = 2;
    NoteViewModel noteViewModel;
    List<Note> allNotes;
    RecyclerView rv;
    NoteAdapter adapter;
    FloatingActionButton floatingActionButton;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        floatingActionButton = (FloatingActionButton) findViewById(R.id.fab);
        rv = (RecyclerView) findViewById(R.id.noterv);
        rv.setLayoutManager(new LinearLayoutManager(this));
        rv.setHasFixedSize(true);

        noteViewModel = ViewModelProviders.of(this).get(NoteViewModel.class);


        noteViewModel.getAllnotes().observe(this, new Observer<List<Note>>() {
            @Override
            public void onChanged(List<Note> notes) {
                adapter = new NoteAdapter(notes);
                rv.setAdapter(adapter);
                adapter.notifyDataSetChanged();
            }
        });

    adapter.SetOnItemClickListener(this) ;



        floatingActionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), AddNoteActivity.class);
                startActivityForResult(intent, ADD_NOTE_REQUEST);

            }
        });

        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,
                ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
            @Override
            public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
                return false;
            }

            @Override
            public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
                noteViewModel.delete(adapter.getAt(viewHolder.getAdapterPosition()));
                Toast.makeText(MainActivity.this, "note has been deleted", Toast.LENGTH_SHORT).show();
            }
        });

        itemTouchHelper.attachToRecyclerView(rv);


    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == ADD_NOTE_REQUEST && resultCode == RESULT_OK) {
            String title = data.getStringExtra("EXTRA_TITLE");
            String description = data.getStringExtra("EXTRA_DESCRIPTION");
            String time = data.getStringExtra("EXTRA_TIME");
            Note note = new Note(title, description, time);
            noteViewModel.insert(note);

        }

        else if (requestCode == EDIT_NOTE_REQUEST && resultCode == RESULT_OK){
            String title = data.getStringExtra("EXTRA_TITLE");
            String description = data.getStringExtra("EXTRA_DESCRIPTION");
            String time = data.getStringExtra("EXTRA_TIME");
            Note note = new Note(title, description, time);
            note.setId(data.getIntExtra("EXTRA_ID",-1));
            noteViewModel.update(note);
            Toast.makeText(this, "note has been updated", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void OnItemClick(Note note) {
        Intent intent =new Intent(MainActivity.this,AddNoteActivity.class);
        intent.putExtra("EXTRA_ID",note.getId());
        intent.putExtra("EXTRA_TITLE",note.getTitle());
        intent.putExtra("EXTRA_DESCRIPTION",note.getDescription());
        intent.putExtra("EXTRA_TIME",note.getModified_time());
        startActivityForResult(intent,EDIT_NOTE_REQUEST);
    }
}

вот мой файл NoteAdapter.java

 package com.example.mynotes;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteViewHolder> {
    OnItemClickListener listener;


    List<Note> notes=new ArrayList<>();

    public NoteAdapter(List<Note> notes) {
        this.notes = notes;
    }

    @NonNull
    @Override
    public NoteViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        Context context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);

        // Inflate the custom layout
        View item_view = inflater.inflate(R.layout.single_note_item, parent, false);

        // Return a new holder instance
        NoteViewHolder viewHolder = new NoteViewHolder(item_view);


        return  viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull NoteViewHolder holder, int position) {
        Note note =notes.get(position);
        holder.titletv.setText(note.getTitle());
        holder.datetv.setText(note.getModified_time());

    }

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

    public class NoteViewHolder extends RecyclerView.ViewHolder{
        TextView titletv ;
        TextView datetv;

        public NoteViewHolder(@NonNull View itemView) {
            super(itemView);
            titletv=(TextView) itemView.findViewById(R.id.titletv);
            datetv=(TextView) itemView.findViewById(R.id.datetv);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (listener !=null && getAdapterPosition() != RecyclerView.NO_POSITION){
                        int position=getAdapterPosition();
                        listener.OnItemClick(notes.get(position));
                    }
                }
            });
        }
    }

    Note getAt(int position){
        return notes.get(position);
    }

    public interface OnItemClickListener{
        void OnItemClick(Note note);
    }
    public void SetOnItemClickListener(OnItemClickListener onItemClickListener){
        this.listener =onItemClickListener;
    }

}

вот мое сообщение Logcat:

 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.mynotes.NoteAdapter.SetOnItemClickListener(com.example.mynotes.NoteAdapter$OnItemClickListener)' on a null object reference
    at com.example.mynotes.MainActivity.onCreate(MainActivity.java:52)
    at android.app.Activity.performCreate(Activity.java:7009)
    at android.app.Activity.performCreate(Activity.java:7000)

Ваш адаптер устанавливается только в обратном вызове onchanged модели представления, и вы пытаетесь установить прослушиватель для объекта адаптера до поступления обратного вызова, поэтому адаптер имеет значение null. Попробуйте установить прослушиватель внутри обратного вызова onchanged.

raxerz 18.05.2019 09:26

спасибо @raxerz за объяснение проблемы...теперь я понял....

Jakaria Masud 18.05.2019 09:59
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
945
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Переместите этот код в наблюдатель

adapter.SetOnItemClickListener(this) ;

Итак, ваш код должен быть таким

 noteViewModel.getAllnotes().observe(this, new Observer<List<Note>>() {
        @Override
        public void onChanged(List<Note> notes) {
            adapter = new NoteAdapter(notes);
            adapter.SetOnItemClickListener(this);
            rv.setAdapter(adapter);
            adapter.notifyDataSetChanged();
        }
    });

сделайте это в своем адаптере и где вы будете new ваш адаптер в действии:

пакет com.example.mynotes;

открытый класс NoteAdapter расширяет RecyclerView.Adapter { Слушатель OnItemClickListener;

List<Note> notes=new ArrayList<>();

public NoteAdapter(List<Note> notes, OnItemClickListener listener) {
    this.notes = notes;
    this.listener = listener;
}

@NonNull
@Override
public NoteViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    Context context = parent.getContext();
    LayoutInflater inflater = LayoutInflater.from(context);

    // Inflate the custom layout
    View item_view = inflater.inflate(R.layout.single_note_item, parent, false);

    // Return a new holder instance
    NoteViewHolder viewHolder = new NoteViewHolder(item_view);


    return  viewHolder;
}

@Override
public void onBindViewHolder(@NonNull NoteViewHolder holder, int position) {
    Note note =notes.get(position);
    holder.titletv.setText(note.getTitle());
    holder.datetv.setText(note.getModified_time());

}

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

public class NoteViewHolder extends RecyclerView.ViewHolder{
    TextView titletv ;
    TextView datetv;

    public NoteViewHolder(@NonNull View itemView) {
        super(itemView);
        titletv=(TextView) itemView.findViewById(R.id.titletv);
        datetv=(TextView) itemView.findViewById(R.id.datetv);
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (listener !=null && getAdapterPosition() != RecyclerView.NO_POSITION){
                    int position=getAdapterPosition();
                    listener.OnItemClick(notes.get(position));
                }
            }
        });
    }
}

Note getAt(int position){
    return notes.get(position);
}

public interface OnItemClickListener{
    void OnItemClick(Note note);
}
public void SetOnItemClickListener(OnItemClickListener onItemClickListener){
    this.listener =onItemClickListener;
  }

}

и теперь в вашей деятельности, где вы будете делать новый адаптер, сделайте следующее:

adapter = new NoteAdapter(notes, NoteAdapter.OnItemClickListener() {
            @Override
            public void OnItemClick(Note note) {
                //DO WHATEVER YOU WANT HERE
            }

Другие вопросы по теме