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