androidsearchnullpointerexceptionandroid-filterable

Why is my Array List throwing a null pointer exception even after initialisation?


I am working on a search feature for my app. I implemented Filterable method to my Home Adapter. My array list is throwing a null pointer exception and I have seen many other similar questions in which the problem was not initializing the array list. However, I have in the following code, but I'm not sure if its initialized in the right place. Please advise me on how to correct this. Thanks.

This is the error I'm getting:

enter image description here

My Home Adapter Code is as follows:

package com.example.oddsynew.Home;

import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;

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

import com.example.oddsynew.Modals.Job;
import com.example.oddsynew.R;
import com.squareup.picasso.Picasso;

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

public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder> implements Filterable {

    Context context;
    ArrayList<Job> jobs, jobsListFull;



    public HomeAdapter(Context c, ArrayList<Job> j) {
        context = c;
        jobs = j;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.job_row, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull final MyViewHolder holder, final int position) {
        holder.recruiterName.setText(jobs.get(position).getRecruiter_name());
        holder.jobName.setText(jobs.get(position).getJob_name());
        holder.jobLocation.setText(jobs.get(position).getLocation());
        holder.jobCharge.setText(jobs.get(position).getJob_charge());
        Picasso.get().load(jobs.get(position).getProf_pic()).into(holder.profPic);

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    Intent intent = new Intent(context, JobInfo.class);
                    intent.putExtra("recruiterName", jobs.get(holder.getAdapterPosition()).getRecruiter_name());
                    intent.putExtra("jobName", jobs.get(holder.getAdapterPosition()).getJob_name());
                    intent.putExtra("jobCharge", jobs.get(holder.getAdapterPosition()).getJob_charge());
                    intent.putExtra("jobLocation", jobs.get(holder.getAdapterPosition()).getLocation());
                    intent.putExtra("profPic", jobs.get(holder.getAdapterPosition()).getProf_pic());
                    intent.putExtra("startDate", jobs.get(holder.getAdapterPosition()).getStart_date());
                    intent.putExtra("endDate", jobs.get(holder.getAdapterPosition()).getEnd_date());
                    intent.putExtra("startTime", jobs.get(holder.getAdapterPosition()).getStart_time());
                    intent.putExtra("endTime", jobs.get(holder.getAdapterPosition()).getEnd_time());
                    intent.putExtra("jobDesc", jobs.get(holder.getAdapterPosition()).getJob_desc());
                    intent.putExtra("jobTasks", jobs.get(holder.getAdapterPosition()).getJob_tasks());
                    intent.putExtra("addPref", jobs.get(holder.getAdapterPosition()).getAdd_pref());
                    intent.putExtra("jobID", jobs.get(holder.getAdapterPosition()).getJobID());
                    context.startActivity(intent);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

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

    @Override
    public Filter getFilter() {
        return searchFilter;
    }

    private Filter searchFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            ArrayList<Job> filteredList = new ArrayList<>();

            if(constraint == null || constraint.length() == 0){
                filteredList.addAll(jobsListFull);
            }else{
                String filterPattern = constraint.toString().toLowerCase().trim();

                for(Job job: jobsListFull){
                    if(job.getJob_name().toLowerCase().contains(filterPattern)){
                        filteredList.add(job);
                    }
                }
            }
            FilterResults results = new FilterResults();
            results.values = filteredList;

            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            jobs.clear();
            jobs.addAll((List) results.values);
            notifyDataSetChanged();

        }
    };

    class MyViewHolder extends RecyclerView.ViewHolder {
        TextView recruiterName, jobName, jobLocation, jobCharge;
        ImageView profPic;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            recruiterName = itemView.findViewById(R.id.recruiterName);
            jobName = itemView.findViewById(R.id.jobName);
            jobLocation = itemView.findViewById(R.id.jobLocation);
            jobCharge = itemView.findViewById(R.id.jobCharge);
            profPic = itemView.findViewById(R.id.prof_pic);
        }
    }

    public HomeAdapter(ArrayList<Job> jobs) {
        this.jobs = jobs;
        jobsListFull = new ArrayList<>(jobs);
    }
}

And this is my search class:

package com.example.oddsynew;

import android.os.Bundle;
import android.widget.SearchView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.example.oddsynew.Home.HomeAdapter;
import com.example.oddsynew.Modals.Job;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import java.util.ArrayList;

public class Search extends AppCompatActivity {

    DatabaseReference myRef;
    RecyclerView newJobList;
    ArrayList<Job> list;
    HomeAdapter adapter;
    SearchView searchView;

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

        newJobList = (RecyclerView) findViewById(R.id.jobRecyclerView);

        searchView = (SearchView) findViewById(R.id.search);

        try {
            newJobList.setLayoutManager(new LinearLayoutManager(Search.this));
            list = new ArrayList<Job>();

            adapter = new HomeAdapter(Search.this, list);
            newJobList.setAdapter(adapter);

            myRef = FirebaseDatabase.getInstance().getReference().child("Jobs");
            myRef.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    for (DataSnapshot ds : dataSnapshot.getChildren()) {
                        Job j = ds.getValue(Job.class);
                        list.add(j);
                    }
                    System.out.println(list);
                    adapter.notifyDataSetChanged();
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {
                    Toast.makeText(Search.this, "Error", Toast.LENGTH_SHORT).show();
                }
            });

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

                @Override
                public boolean onQueryTextChange(String newText) {
                    adapter.getFilter().filter(newText);
                    return false;
                }
            });

        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}

SOLUTION: With IntelliJ Amiya's help I came up with the following corrected code.

 @Override
    public Filter getFilter() {
        return searchFilter;
    }

    private Filter searchFilter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                String charString = charSequence.toString();
                if (charString.isEmpty()) {
                    jobs = jobsListFull;
                } else {
                    ArrayList<Job> filteredList = new ArrayList<>();
                    for (Job row : jobsListFull) {


                        if (row.getJob_name().toLowerCase().contains(charString.toLowerCase())) {
                            filteredList.add(row);
                        }
                    }

                    jobs = filteredList;
                }

                FilterResults filterResults = new FilterResults();
                filterResults.values = jobs;
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                jobs = ((ArrayList) filterResults.values);
                notifyDataSetChanged();
            }
        };

    class MyViewHolder extends RecyclerView.ViewHolder {
        TextView recruiterName, jobName, jobLocation, jobCharge;
        ImageView profPic;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            recruiterName = itemView.findViewById(R.id.recruiterName);
            jobName = itemView.findViewById(R.id.jobName);
            jobLocation = itemView.findViewById(R.id.jobLocation);
            jobCharge = itemView.findViewById(R.id.jobCharge);
            profPic = itemView.findViewById(R.id.prof_pic);
        }
    }

Solution

  • jobs.addAll((List) results.values);

    addAll() appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection's Iterator.

     @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                jobs.clear();
                jobs.addAll((List) results.values); // Issue here
                notifyDataSetChanged();
    
            }
        };
    

    In Java, a special null value can be assigned to an object reference. NullPointerException is thrown when an application attempts to use an object reference that has the null value.

    Your (List) results.values return null. At first debug (Add Break-point) that values are present or not FilterResults results. Before cast to List make sure results.values having data.

    CODE EDIT

    package com.example.oddsynew.Home;
    
    import android.content.Context;
    import android.content.Intent;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Filter;
    import android.widget.Filterable;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import androidx.annotation.NonNull;
    import androidx.recyclerview.widget.RecyclerView;
    
    import com.example.oddsynew.Modals.Job;
    import com.example.oddsynew.R;
    import com.squareup.picasso.Picasso;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder> implements Filterable {
    
        Context context;
    
        private ArrayList<Job> alListData;
        private ArrayList<Job> alListFiltered;
    
    
        public HomeAdapter(Context c, ArrayList<Job> j) {
             context = c;
             this.alListData = j;
             this.alListFiltered = j;
        }
    
        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.job_row, parent, false));
        }
    
        @Override
        public void onBindViewHolder(@NonNull final MyViewHolder holder, final int position) {
            holder.recruiterName.setText(alListFiltered.get(position).getRecruiter_name());
            holder.jobName.setText(alListFiltered.get(position).getJob_name());
            holder.jobLocation.setText(alListFiltered.get(position).getLocation());
            holder.jobCharge.setText(alListFiltered.get(position).getJob_charge());
            Picasso.get().load(alListFiltered.get(position).getProf_pic()).into(holder.profPic);
    
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    try {
                        Intent intent = new Intent(context, JobInfo.class);
                        intent.putExtra("recruiterName", alListFiltered.get(holder.getAdapterPosition()).getRecruiter_name());
                        intent.putExtra("jobName", alListFiltered.get(holder.getAdapterPosition()).getJob_name());
                        intent.putExtra("jobCharge", alListFiltered.get(holder.getAdapterPosition()).getJob_charge());
                        intent.putExtra("jobLocation", alListFiltered.get(holder.getAdapterPosition()).getLocation());
                        intent.putExtra("profPic", alListFiltered.get(holder.getAdapterPosition()).getProf_pic());
                        intent.putExtra("startDate", alListFiltered.get(holder.getAdapterPosition()).getStart_date());
                        intent.putExtra("endDate", alListFiltered.get(holder.getAdapterPosition()).getEnd_date());
                        intent.putExtra("startTime", alListFiltered.get(holder.getAdapterPosition()).getStart_time());
                        intent.putExtra("endTime", alListFiltered.get(holder.getAdapterPosition()).getEnd_time());
                        intent.putExtra("jobDesc", alListFiltered.get(holder.getAdapterPosition()).getJob_desc());
                        intent.putExtra("jobTasks", alListFiltered.get(holder.getAdapterPosition()).getJob_tasks());
                        intent.putExtra("addPref", alListFiltered.get(holder.getAdapterPosition()).getAdd_pref());
                        intent.putExtra("jobID", alListFiltered.get(holder.getAdapterPosition()).getJobID());
                        context.startActivity(intent);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    
        @Override
        public int getItemCount() {
            return alListFiltered.size();
        }
    
        @Override
        public Filter getFilter() {
            return searchFilter;
        }
    
        @Override
        public Filter getFilter() {
            return new Filter() {
                @Override
                protected FilterResults performFiltering(CharSequence charSequence) {
                    String charString = charSequence.toString();
                    if (charString.isEmpty()) {
                        alListFiltered = alListData;
                    } else {
                        List<Job> filteredList = new ArrayList<>();
                        for (Job row : alListData) {
    
    
                            if (row.getJob_name().toLowerCase().contains(charString.toLowerCase())) {
                                filteredList.add(row);
                            }
                        }
    
                        alListFiltered = filteredList;
                    }
    
                    FilterResults filterResults = new FilterResults();
                    filterResults.values = alListFiltered;
                    return filterResults;
                }
    
                @Override
                protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                    alListFiltered = (ArrayList<Job>) filterResults.values;
                    notifyDataSetChanged();
                }
            };
        }
    
    
        class MyViewHolder extends RecyclerView.ViewHolder {
            TextView recruiterName, jobName, jobLocation, jobCharge;
            ImageView profPic;
    
            public MyViewHolder(@NonNull View itemView) {
                super(itemView);
                recruiterName = itemView.findViewById(R.id.recruiterName);
                jobName = itemView.findViewById(R.id.jobName);
                jobLocation = itemView.findViewById(R.id.jobLocation);
                jobCharge = itemView.findViewById(R.id.jobCharge);
                profPic = itemView.findViewById(R.id.prof_pic);
            }
        }
    
    }