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