Search code examples
androidandroid-fragmentsandroid-recyclerviewsearchview

RecyclerView with SearchView will not populate upon initialization


I am currently using searchView to filter results on a RecyclerView. The problem is when the fragment is initialized, the list won't appear not until I click on the search icon on the toolbar and type some texts on it. I've tried modifying the codes. Take a look specifically at the adapter and holder classes, if you'll try to exchange my current codes to these:

    public MembershipActivationAdapter(Context context, List<Member> members){
        this.context = context;
        this.mMembers = members;
    }

and

    @Override
    public MembershipActivationViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        final View itemView = LayoutInflater.from(context).inflate(R.layout.member_activation_content, viewGroup, false);
    }

,it will show the list upon calling the fragment however if I'll type something on the SearchView, it seems to function only as a one way filter. It will filter names but whenever I'll try to remove a character or a text on the searchview, it won't show the list back. Please help me with this. These are my codes:

Adapter & ViewHolder class:

    public class MembershipActivationAdapter extends RecyclerView.Adapter<MembershipActivationAdapter.MembershipActivationViewHolder> {

        private final List<Member> mMembers;
        private final LayoutInflater inflater;
        //private final Context context;

        public MembershipActivationAdapter(Context context, List<Member> members){
            inflater = LayoutInflater.from(context);
            mMembers = new ArrayList<>(members);
            //this.context = context;
            //this.mMembers = members;
        }

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

    @Override
    public void onBindViewHolder(MembershipActivationViewHolder holder, final int position) {
        final Member m = mMembers.get(position);

        holder.name.setText(m.getName());

        holder.email.setText(m.getEmail());
        if(m.getStatus().equals("Active")){
            holder.status.setText(Html.fromHtml("<font color='#00CD00'>" + m.getStatus() + "</font>"));
        }else{
            holder.status.setText(Html.fromHtml("<font color='#ff0000'>" + m.getStatus() + "</font>"));
        }
    }

    @Override
    public MembershipActivationViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        final View itemView = inflater.inflate(R.layout.member_activation_content, viewGroup, false);
        return new MembershipActivationViewHolder(itemView);
        //final View itemView = LayoutInflater.from(context).inflate(R.layout.member_activation_content, viewGroup, false);
    }

    public static class MembershipActivationViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public final TextView name;
        public final TextView email;
        public final TextView status;

        public MembershipActivationViewHolder(View v) {
            super(v);
            v.setOnClickListener(this);
            name = (TextView) v.findViewById(R.id.member_name);
            email = (TextView) v.findViewById(R.id.member_email);
            status = (TextView) v.findViewById(R.id.member_status);
        }
    }
    public List<Member> getMemberList() {
        return mMembers;
    }

    public void animateTo(List<Member> members) {
        applyAndAnimateRemovals(members);
        applyAndAnimateAdditions(members);
        applyAndAnimateMovedItems(members);
    }

    private void applyAndAnimateRemovals(List<Member> newMembers) {
        for (int i = mMembers.size() - 1; i >= 0; i--) {
            final Member member = mMembers.get(i);
            if (!newMembers.contains(member)) {
                removeItem(i);
            }
        }
    }

    private void applyAndAnimateAdditions(List<Member> newMembers) {
        for (int i = 0, count = newMembers.size(); i < count; i++) {
            final Member member = newMembers.get(i);
            if (!mMembers.contains(member)) {
                addItem(i, member);
            }
        }
    }

    private void applyAndAnimateMovedItems(List<Member> newMembers) {
        for (int toPosition = newMembers.size() - 1; toPosition >= 0; toPosition--) {
            final Member member = newMembers.get(toPosition);
            final int fromPosition = mMembers.indexOf(member);
            if (fromPosition >= 0 && fromPosition != toPosition) {
                moveItem(fromPosition, toPosition);
            }
        }
    }

    public Member removeItem(int position) {
        final Member member = mMembers.remove(position);
        notifyItemRemoved(position);
        return member;
    }

    public void addItem(int position, Member member) {
        mMembers.add(position, member);
        notifyItemInserted(position);
    }

    public void moveItem(int fromPosition, int toPosition) {
        final Member member = mMembers.remove(fromPosition);
        mMembers.add(toPosition, member);
        notifyItemMoved(fromPosition, toPosition);
    }
    }

Fragment Class:

    public class MembershipActivationFragment extends Fragment implements SearchView.OnQueryTextListener{

    private static String url = "http://www.xxxxx.org/portal/webservices/get_members.php";
    private List<Member> memberList;
    private RecyclerView recyclerView;
    private MembershipActivationAdapter adapter;
    private String pid;
    private ProgressDialog progressDialog;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.member_activation, container, false);

        recyclerView = (RecyclerView) rootView.findViewById(R.id.members_recycler_view);

        setHasOptionsMenu(true);
        memberList = new ArrayList<>();
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        progressDialog = new ProgressDialog(getActivity());
        progressDialog.setMessage("Loading...");
        progressDialog.show();
        populate();

        return rootView;
    }

    public void populate(){
        JsonArrayRequest request = new JsonArrayRequest(url,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray jsonArray) {
                        hidePDialog();
                        String  name, email, status;
                        Member member;
                        for(int i = 0; i < jsonArray.length(); i++) {
                            try {
                                JSONObject object = jsonArray.getJSONObject(i);
                                name = object.getString("firstname") + " " + object.getString("lastname");
                                email = object.getString("email");
                                if(Integer.parseInt(object.getString("activated"))==1){
                                    status = "Active";
                                }else{
                                    status = "Not Active";
                                }
                                member = new Member(name, email, status);

                                memberList.add(member);
                            } catch (Exception e) {

                            }
                        }
                        adapter.notifyDataSetChanged();
                    }
                }, new Response.ErrorListener(){
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                volleyError.printStackTrace();
            }
        });
        AppController.getInstance().addToRequestQueue(request);
        adapter = new MembershipActivationAdapter(getActivity(), memberList);
        recyclerView.setAdapter(adapter);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.search_menu, menu);

        final MenuItem item = menu.findItem(R.id.action_search);
        final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
        searchView.setOnQueryTextListener(this);
    }

    @Override
    public boolean onQueryTextChange(String query) {
        final List<Member> filteredMemberList = filter(memberList, query);
        adapter.animateTo(filteredMemberList);
        recyclerView.scrollToPosition(0);
        return true;
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
        return false;
    }

    private List<Member> filter(List<Member> members, String query) {
        query = query.toLowerCase();

        final List<Member> filteredModelList = new ArrayList<>();
        for (Member member : members) {
            final String text = member.getName().toLowerCase();
            if (text.contains(query)) {
                filteredModelList.add(member);
            }
        }
        return filteredModelList;
    }

    private void hidePDialog() {
        if (progressDialog != null) {
            progressDialog.dismiss();
            progressDialog = null;
        }
    }
    }

RecyclerView container xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
    android:id="@+id/members_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"/>

    </LinearLayout>

Content class:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:padding="5dip">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Name here"
        android:textStyle="bold"
        android:id="@+id/member_name"
        android:layout_centerVertical="true"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="email@gmail.com"
        android:id="@+id/member_email"
        android:layout_below="@+id/member_name"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="email@gmail.com"
        android:id="@+id/member_status"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"/>

    </RelativeLayout>

    </LinearLayout>

Model Class:

    public class Member {

    private String name;
    private String email;
    private String status;

    public Member(String name, String email, String status) {
        this.name = name;
        this.email = email;
        this.status = status;
    }
    public Member(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
    }

Solution

  • Atlast! I was able to find the resolution for this. Kudos to the developer himself, Xaver Kapeller!

        public void populate(){
            JsonArrayRequest request = new JsonArrayRequest(url,
                    new Response.Listener<JSONArray>() {
                        @Override
                        public void onResponse(JSONArray jsonArray) {
    //                        hidePDialog();
                            String   email, status;
    //                        Member member;
                            for(int i = 0; i < jsonArray.length(); i++) {
                                try {
                                    JSONObject object = jsonArray.getJSONObject(i);
    
                                    final String name = object.getString("firstname") + " " + object.getString("lastname");
                                    email = object.getString("email");
                                    if(Integer.parseInt(object.getString("activated"))==1){
                                        status = "Active";
                                    }else{
                                        status = "Not Active";
                                    }
                                    mModels.add(new ExampleModel(name));
    //                                member = new Member(name, email, status);
    
                                } catch (Exception e) {
    
                                }
                            }
                            mAdapter = new ExampleAdapter(getActivity(), mModels);
                            mRecyclerView.setAdapter(mAdapter);
                        }
                    }, new Response.ErrorListener(){
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                    volleyError.printStackTrace();
                }
            });
            AppController.getInstance().addToRequestQueue(request);
    
        }
    

    Just tranfer these two lines of code inside onResponse() and everything will work perfectly fine:

    mAdapter = new ExampleAdapter(getActivity(), mModels);
    mRecyclerView.setAdapter(mAdapter);