Search code examples
androidandroid-studioandroid-recyclerviewsearchview

Blank output on RecyclerView when applying filters using searchview


I am following a tutorial to implement a filter on my RecyclerView with SearchView. As soon as I type something in the search query, my RecyclerView goes blank. i have been banging my head on this one from hours and I feel nowhere near the solution.

Here is the my Adapter Class

package com.example.internetconnectivityapplication;

import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;

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

public class DataAdapter extends RecyclerView.Adapter<DataAdapter.MyViewHolder> implements Filterable {
    private List<Data> dataList;
    private List<Data> dataListFull;

    public class MyViewHolder extends RecyclerView.ViewHolder{
        public TextView dataName;
        public MyViewHolder(View view){
            super(view);
            dataName = (TextView) view.findViewById(R.id.data_name);
        }

    }

    public DataAdapter(List<Data> dataList){
        this.dataList = dataList;
        this.dataListFull = new ArrayList<>(dataList);
    }

    @NonNull
    @Override
    public DataAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View viewItem = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.data_row,viewGroup,false);
        return new MyViewHolder(viewItem);
    }

    @Override
    public void onBindViewHolder(@NonNull DataAdapter.MyViewHolder myViewHolder, int i) {
        Data data = dataList.get(i);
        myViewHolder.dataName.setText(data.getDataString());
    }

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

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

    private Filter dataFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            List<Data> filteredDataList = new ArrayList<>();

            if(constraint == null || constraint.length() == 0){
                filteredDataList.addAll(dataListFull);
            } else {
                String filterParameter = constraint.toString().toLowerCase().trim();
                for(Data data : dataListFull){
                    if(data.getDataString().toLowerCase().trim().contains(filterParameter)){
                        filteredDataList.add(data);
                    }
                }
            }
            FilterResults filterResults = new FilterResults();
            filterResults.values = filteredDataList;

            return filterResults;
        }

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

Here is Model Class

package com.example.internetconnectivityapplication;


public class Data {
    String dataString;

    public Data(String dataString){
        this.dataString = dataString;
    }
    public String getDataString(){
        return dataString;
    }

}

Here is MainActivity Class

package com.example.internetconnectivityapplication;

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

import org.apache.commons.io.IOUtils;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.net.ssl.HttpsURLConnection;

public class MainActivity extends AppCompatActivity {
    private List<Data> dataList = new ArrayList<>();
    private RecyclerView recyclerView;
    private DataAdapter dataAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        dataAdapter = new DataAdapter(dataList);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(dataAdapter);
        new GetData().execute();
    }

    private class GetData extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... voids) {
            try {
                // Create URL
                URL githubEndpoint = new URL("https://api.github.com/");

                // Create connection
                HttpsURLConnection myConnection =
                        (HttpsURLConnection) githubEndpoint.openConnection();
                myConnection.setRequestProperty("User-Agent", "my-rest-app-v0.1");
                myConnection.setRequestMethod("GET");
                String responseString = IOUtils.toString(myConnection.getInputStream(), "UTF-8");
                JSONObject responseJson = (JSONObject) new JSONParser().parse(responseString);
                Set<String> keyValues = responseJson.keySet();
                for (String key : keyValues) {
                    Data data = new Data(responseJson.get(key).toString());
                    Log.d("Data Element: ", data.getDataString());
                    dataList.add(data);
                }
                for (Data data : dataList) {
                    Log.d("Data List Element", data.getDataString());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            dataAdapter.notifyDataSetChanged();
            super.onPostExecute(aVoid);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.search_menu,menu);
        MenuItem searchItem = menu.findItem(R.id.search_action);
        SearchView searchView = (SearchView) searchItem.getActionView();

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                dataAdapter.getFilter().filter(s);
                return false;
            }
            @Override
            public boolean onQueryTextChange(String s) {
                dataAdapter.getFilter().filter(s);
                return false;
            }
        });

        return true;
    }
}

Solution

  • You have to save your list twice , Once for the recyclerview and the other one for filtering.

    Look at the working example below

    getUserModelListFiltered is used only for filtering purposes.

    public class UsersAdapter extends RecyclerView.Adapter<UsersAdapter.UsersAdapterVh> implements Filterable {
    
        private List<UserModel> userModelList;
        private List<UserModel> getUserModelListFiltered;
        private Context context;
        private SelectedUser selectedUser;
    
        public UsersAdapter(List<UserModel> userModelList,SelectedUser selectedUser) {
            this.userModelList = userModelList;
            this.getUserModelListFiltered = userModelList;
            this.selectedUser = selectedUser;
        }
    
        @NonNull
        @Override
        public UsersAdapter.UsersAdapterVh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            context = parent.getContext();
    
            return new UsersAdapterVh(LayoutInflater.from(context).inflate(R.layout.row_uses,null));
        }
    
        @Override
        public void onBindViewHolder(@NonNull UsersAdapter.UsersAdapterVh holder, int position) {
    
            UserModel userModel = userModelList.get(position);
    
            String username = userModel.getUserName();
            String prefix = userModel.getUserName().substring(0,1);
    
            holder.tvUsername.setText(username);
            holder.tvPrefix.setText(prefix);
        }
    
    
    
    
        @Override
        public int getItemCount() {
            return userModelList.size();
        }
    
        @Override
        public Filter getFilter() {
    
            Filter filter = new Filter() {
                @Override
                protected FilterResults performFiltering(CharSequence charSequence) {
                    FilterResults filterResults = new FilterResults();
    
                    if(charSequence == null | charSequence.length() == 0){
                        filterResults.count = getUserModelListFiltered.size();
                        filterResults.values = getUserModelListFiltered;
    
                    }else{
                        String searchChr = charSequence.toString().toLowerCase();
    
                        List<UserModel> resultData = new ArrayList<>();
    
                        for(UserModel userModel: getUserModelListFiltered){
                            if(userModel.getUserName().toLowerCase().contains(searchChr)){
                                resultData.add(userModel);
                            }
                        }
                        filterResults.count = resultData.size();
                        filterResults.values = resultData;
    
                    }
    
                    return filterResults;
                }
    
                @Override
                protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
    
                    userModelList = (List<UserModel>) filterResults.values;
                    notifyDataSetChanged();
    
                }
            };
            return filter;
        }
    
    
        public interface SelectedUser{
    
            void selectedUser(UserModel userModel);
    
        }
    
        public class UsersAdapterVh extends RecyclerView.ViewHolder {
    
            TextView tvPrefix;
            TextView tvUsername;
            ImageView imIcon;
            public UsersAdapterVh(@NonNull View itemView) {
                super(itemView);
                tvPrefix = itemView.findViewById(R.id.prefix);
                tvUsername = itemView.findViewById(R.id.username);
                imIcon = itemView.findViewById(R.id.imageView);
    
                itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        selectedUser.selectedUser(userModelList.get(getAdapterPosition()));
                    }
                });
    
    
            }
        }
    }