0

I have searched a lot and didn't find any solution for my problem.I have created an interface for handling click listeners on particular item on recycler view.Logcat shows the error is occured in setting the listener in maiactivity

here is my MainActivity.java file

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);
    }
}

here is my NoteAdapter.java file

 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;
    }

}

here is my Logcat message:

 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)
Jakaria Masud
  • 37
  • 1
  • 4
  • Your adapter is being set only in the onchanged callback of the view model and you're trying to set the listener on the adapter object before the callback arrives which is why the adapter is null. Try setting the listener inside the onchanged callback. – raxerz May 18 '19 at 07:26
  • thanks @raxerz for explaining the problem...now i have understood it.... – Jakaria Masud May 18 '19 at 07:59

2 Answers2

1

Move this code to observer

adapter.SetOnItemClickListener(this) ;

So your code must be like 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();
        }
    });
Radesh
  • 10,690
  • 3
  • 42
  • 60
0

do this in your adapter and where you will new your adapter in activity:

package com.example.mynotes;

public class NoteAdapter extends RecyclerView.Adapter { OnItemClickListener listener;

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;
  }

}

and now in your activity where you will new your adapter do this:

adapter = new NoteAdapter(notes, NoteAdapter.OnItemClickListener() {
            @Override
            public void OnItemClick(Note note) {
                //DO WHATEVER YOU WANT HERE
            }
Tamir Abutbul
  • 6,472
  • 7
  • 16
  • 44
Arash Afsharpour
  • 994
  • 7
  • 19