Search code examples
androidandroid-recyclerviewadapter

Why item select doesn't work in recyclerview on normal list but works in search list?


I have created arraylist for projects which is stored in firebase database. I was able to list the projects in recyclerview. Even search too works fine. But when it comes to clicking an item in the recyclerview list, the click works in search list but doesn't work in normal list. The code is given below

public class MainActivity extends AppCompatActivity implements Adapter.SelectedProject {

    DatabaseReference mDatabase;
    ArrayList<projects> list;
    RecyclerView PList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        PList = findViewById(R.id.ProjList);
        PList.setHasFixedSize(true);
        mDatabase = FirebaseDatabase.getInstance().getReference().child("Projects");
    }

    @Override
    protected void onStart() {
        super.onStart();

        if (mDatabase != null) {

            mDatabase.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                    if (dataSnapshot.exists()) {

                        list = new ArrayList<>();
                        for (DataSnapshot ds : dataSnapshot.getChildren()) {
                            list.add(ds.getValue(projects.class));
                        }
                        Adapter adapter = new Adapter(list, null);
                        PList.setAdapter(adapter);
                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {

                    Toast.makeText(MainActivity.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();

                }
            });
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_home, menu);
        MenuItem item = menu.findItem(R.id.search);
        SearchView searchView = (SearchView) item.getActionView();

        if (searchView != null) {

            searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                @Override
                public boolean onQueryTextSubmit(String query) {
                    return false;
                }

                @Override
                public boolean onQueryTextChange(String newText) {
                    search(newText);
                    return true;
                }
            });
        }

        return super.onCreateOptionsMenu(menu);
    }

    private void search(String str) {

        ArrayList<projects> sList = new ArrayList<>();

        for (projects object : list) {

            if (object.getPname().toLowerCase().contains(str.toLowerCase())) {

                sList.add(object);
            }

        }
        Adapter adapter = new Adapter(sList, this);
        PList.setAdapter(adapter);

    }

    @Override
    public void selectedProject(projects projects) {
        startActivity(new Intent(MainActivity.this, InfoActivity.class));
    }
}

Adapter Class

public class Adapter extends RecyclerView.Adapter < Adapter.ProjViewHolder > {

    private ArrayList < projects > list;
    private SelectedProject selectedProject;

    public Adapter(ArrayList < projects > list, SelectedProject selectedProject) {

        this.list = list;
        this.selectedProject = selectedProject;
    }

    @NonNull
    @Override
    public ProjViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.proj_list, parent, false);
        return new ProjViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ProjViewHolder holder, int position) {

        holder.prname.setText(list.get(position).getPname());
        holder.prlocation.setText(list.get(position).getPlocation());

    }

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

    public interface SelectedProject {
        void selectedProject(projects projects);
    }

    class ProjViewHolder extends RecyclerView.ViewHolder {

        TextView prname, prlocation;

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

            prname = itemView.findViewById(R.id.FPName);
            prlocation = itemView.findViewById(R.id.FPLocation);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    selectedProject.selectedProject(list.get(getAdapterPosition()));
                }
            });
        }
    }
}

The selection is accepted in the search adapter.

Adapter adapter = new Adapter(sList,this);

But normal adapter shows error for the below code.

Adapter adapter = new Adapter(list,this);

But if i change this to null as below, the error goes off.

Adapter adapter = new Adapter(list,null);

But when I clicked, the app is closed.

Please let me know how to correct the error?

stackrace details

 java.lang.NullPointerException: Attempt to invoke interface method 'void com.example.volq.Adapter$SelectedProject.selectedProject(com.example.volq.projects)' on a null object reference
    at com.example.volq.Adapter$ProjViewHolder$1.onClick(Adapter.java:68)
    at android.view.View.performClick(View.java:5610)
    at android.view.View$PerformClick.run(View.java:22265)
    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:6077)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

Solution

  • Notice the difference between how you're setting your adapter for search vs normal

    Adapter adapter = new Adapter(sList, this); // `this`as the second parameter/listener is ok
    

    But for the other one:

    Adapter adapter = new Adapter(list, null);
    

    Here the listener is null, this error makes sense:

    java.lang.NullPointerException: Attempt to invoke interface method 'void com.example.volq.Adapter$SelectedProject.selectedProject(com.example.volq.projects)' on a null object reference

    Instead of null, just pass MainActivity.this in your Activity's onStart() callback:

    Adapter adapter = new Adapter(list, MainActivity.this);

    But normal adapter shows error for the below code.

    Adapter adapter = new Adapter(list,this);

    It's because of this does not reference MainActivity inside onDataChange() callback, it refers to the ValueEventListener