Search code examples
androidandroid-recyclerviewandroid-volleysearchviewandroid-filterable

SearchView for RecyclerView not working


I have implemented searchview filter for recyclerview in fragment like below but when I am entering the query in searchview nothing happens .

My Fragment class: DiscussionForum.java

public class DiscussionForum extends Fragment implements ForumAdapter.ForumAdapterListener {


private TextView socname;
private EditText messageinput;
private SearchView search;
// SearchView searchView;
private FloatingActionButton messagesend;
ProgressDialog progressDialog;
private static final String TAG = "Discussion Forum";
private RecyclerView recyclerView;
private List<ForumData> forumlist;
private ForumAdapter mAdapter;
private OnFragmentInteractionListener mListener;
private LinearLayout list;
private String sendurl, geturl;

public DiscussionForum() {
    // Required empty public constructor
}


public static DiscussionForum newInstance(String param1, String param2) {
    DiscussionForum fragment = new DiscussionForum();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
}

@Override

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {      
    View view = inflater.inflate(R.layout.fragment_discussion_forum, container, false);
    onButtonPressed("Discussion Forum");      
    forumlist = new ArrayList<>();
    recyclerView = view.findViewById(R.id.listviewforum);
    list = view.findViewById(R.id.list);
    search = view.findViewById(R.id.search);
    int resId = R.anim.layout_animation_fall_down;
    LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(getContext(), resId);
    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getContext());
    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.setLayoutAnimation(animation);
    mAdapter = new ForumAdapter(getContext(), forumlist, this);
    progressDialog = new ProgressDialog(getContext());
    progressDialog.setCancelable(false);        
    geturl = "";         
    fetchforumdata(getActivity().getIntent().getStringExtra("id"));
    search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

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

    return view;
}



private void fetchforumdata(final String id1) {
    progressDialog.setMessage("Loading...");
    showDialog();
    StringRequest request = new StringRequest(Request.Method.GET,
            geturl + id1,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    // Log.d("tag2","id"+id1);
                    Log.d(TAG, "Response Prop: " + response.toString());
                    hideDialog();
                    try {
                        JSONObject jObj = new JSONObject(response);
                        boolean error = jObj.getBoolean("errors");
                        if (!error) {
                            JSONObject dataobj = jObj.getJSONObject("data");
                            JSONArray ticketarray = dataobj.getJSONArray("result");
                            if (ticketarray.length() == 0) {
                                list.setVisibility(View.VISIBLE);
                            } else {
                                recyclerView.setVisibility(View.VISIBLE);
                                List<ForumData> items = new Gson().fromJson(ticketarray.toString(), new TypeToken<List<ForumData>>() {
                                }.getType());

                                forumlist.clear();
                                forumlist.addAll(items);
                                recyclerView.setAdapter(mAdapter);
                            }
                        } else {
                            // String errorMsg = jObj.getString("error_msg");
                            Toast.makeText(getContext(),
                                    "Try again or report an issue", Toast.LENGTH_LONG).show();
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            // error in getting json
            Log.e(TAG, "Error: " + error.getMessage());
            Toast.makeText(getContext(), "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
            hideDialog();
        }
    });

    MyApplication.getInstance().addToRequestQueue(request);
}


// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(String title) {
    if (mListener != null) {
        mListener.onFragmentInteraction(title);
    }
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnFragmentInteractionListener) {
        mListener = (OnFragmentInteractionListener) context;
    } else {
        throw new RuntimeException(context.toString()
                + " must implement OnFragmentInteractionListener");
    }
}

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

private void showDialog() {
    if (!progressDialog.isShowing())
        progressDialog.show();
}

private void hideDialog() {
    if (progressDialog.isShowing())
        progressDialog.dismiss();
}

@Override
public void onDocumentSelected(String id) {

}

public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(String title);
}}

My Adapter Class :ForumAdapter

public class ForumAdapter extends RecyclerView.Adapter<ForumAdapter.MyViewHolder> implements Filterable {
private Context context;
private List<ForumData> ticketlist;
private List<ForumData> filterlist;
private ForumAdapterListener listener;




public class MyViewHolder extends RecyclerView.ViewHolder {
    TextView username,createdat,forummessage,flatno,category,likes,subcount;
    ImageView edit;

    public MyViewHolder(View view) {
        super(view);
        username=view.findViewById(R.id.user_name2);
        createdat=view.findViewById(R.id.date2);
        edit = view.findViewById(R.id.profile_icon2);
        forummessage=view.findViewById(R.id.forum_message);
        flatno=view.findViewById(R.id.flat_no);
        category=view.findViewById(R.id.category);
        likes=view.findViewById(R.id.likes_data);
        subcount=view.findViewById(R.id.count_data);

    }
}
public ForumAdapter(Context context, List<ForumData> ticketlist, ForumAdapterListener listener) {
    this.context = context;
    this.listener = listener;
    this.ticketlist = ticketlist;
    this.filterlist=ticketlist;
}

@Override
public ForumAdapter.MyViewHolder onCreateViewHolder( ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.discussion_forum_item, parent, false);

    return new MyViewHolder(itemView);
}

@Override
public void onBindViewHolder( ForumAdapter.MyViewHolder holder, int position) {
    final ForumData contact = ticketlist.get(position);
    holder.username.setText(contact.getUsername());
    holder.flatno.setText(contact.getFlattitle());
    holder.forummessage.setText(contact.getMessage());
    holder.createdat.setText(contact.getCreated_at());
    holder.category.setText(contact.getCategory());      
    holder.likes.setText(contact.getLikes());       
    holder.subcount.setText(contact.getSubcount());
    Glide.with(context)
            .load(url+".jpg")
            .apply(new RequestOptions().circleCrop().placeholder(R.drawable.man).error(R.drawable.man))
            .into(holder.edit);

        }
    });

}

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


@Override
public Filter getFilter() {
    return new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence charSequence) {
            String charString = charSequence.toString();
            if (charString.isEmpty()) {
                filterlist = ticketlist;
            } else {
                List<ForumData> filteredList = new ArrayList<>();
                for (ForumData row : ticketlist) {

                    // name match condition. this might differ depending on your requirement
                    // here we are looking for name or phone number match
                    if (row.getUsername().toLowerCase().contains(charString.toLowerCase()) || row.getCategory().contains(charSequence)) {
                        filteredList.add(row);
                    }
                }

                filterlist = filteredList;
            }

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

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            filterlist = (ArrayList<ForumData>) results.values;
            notifyDataSetChanged();

        }
    }
     ;
}
public interface ForumAdapterListener {
    void onDocumentSelected(String contact);
}}

I have gone through many solutions like here , here ,here
But I am unable to figure out what is wrong with my code . Please help me figure out where the exact problem is.


Solution

  • There are multiple issues with your Adapter implementation. If I understand your code correctly you want to keep a reference to a list of unfiltered items (List<ForumData> ticketlist) and filter this list and display the filtered results (List<ForumData> filterlist) on the screen.

    Firstly, you want to display filterlist on the screen so in onBindViewHolder() and getItemCount() you need to use filterlist instead of ticketlist.

    Secondly, you want to ensure that ticketlist stays unchanged so that all future searches are on the same content. To do this you will have to replace all filterlist = ticketlist; with filterlist = new ArrayList<>(ticketlist); (in your contstructor and in performFiltering()) to avoid changing the contents of ticketlist.

    This should make your code functional at least. I suggest you watch this video on Java and objects and references as well.