0

Here is the code I am not able to implement search in heterogeneous recyclerview with two different viewholders. Can anyone suggest me something. Moreover my views of recyclerview are textViews and cardViews. CardView is having data written on it for example name, age and phone number. I want to search with the name and phone number. Nothing with the date textView.

See publishResults image

Thanks in advance.

Here is my code :

            if (charString.isEmpty()) {
                // Search is empty/Nothing Entered
                mAppointmentsList = mAppointmentsListFiltered;
            } else {
                List<DataAppointments> filterResults = new ArrayList<>();

                for (DataAppointments data : mAppointmentsList) {
                    if (data instanceof DataPatientDetails) {
                        DataPatientDetails details = (DataPatientDetails) data;

                        if (details.getName().toLowerCase().contains(charString.toLowerCase()) ||
                                details.getPhone().toLowerCase().contains(charString.toLowerCase()) ||
                                details.getId().toLowerCase().contains(charString.toLowerCase())) {
                            filterResults.add(data);

                            if (BuildConfig.DEBUG)
                                Log.d(TAG, "performFiltering: " + details.getName());
                        }
                    }
                }

                mAppointmentsListFiltered = filterResults;
                if (BuildConfig.DEBUG)
                    Log.d(TAG, "performFilteringPatientListFiltered: " + mAppointmentsListFiltered);
            }

            FilterResults results = new FilterResults();
            results.values = mAppointmentsListFiltered;
            results.count = mAppointmentsListFiltered.size();
            if (BuildConfig.DEBUG)
                Log.d(TAG, "performFilteringResultsUpcoming: " + results.count);
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            mAppointmentsListFiltered = (ArrayList<DataAppointments>) results.values;
            if (BuildConfig.DEBUG) Log.d(TAG, "publishResults: " + mAppointmentsListFiltered);
            notifyDataSetChanged();
        }
    };
}`

And my onQueryChangeListener :

    // Query Search in Material Search view
private void querySearch() {
    if (getActivity() != null)
        mSearchView = getActivity().findViewById(R.id.search_view_upcoming);
    mSearchView.setOnQueryTextListener(new MaterialSearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            if (BuildConfig.DEBUG) Log.d(TAG, "onQueryTextSubmit: " + query);
            mAdapter.getFilter().filter(query);
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            if (BuildConfig.DEBUG) Log.d(TAG, "onQueryTextChange: " + newText);
            mAdapter.getFilter().filter(newText);
            if (BuildConfig.DEBUG) Log.d(TAG, "onQueryTextChange: " + mAdapter.getItemCount());

            return false;
        }
    });
}
Mani Kumar
  • 56
  • 1
  • 7
  • Implementing search should be view agnostic. Apply the filter on your data list. Post the code if you can. – Binary Baba Jun 29 '18 at 05:14
  • @RickSanchez i want to filter on the basis of data related to one type of view that is cardView only. Moreover they both have different dataModels and so is their getters and setters. So for comparison in Filter() i am not getting how to compare them. Because i am using a list (parent dataModel type, that has both kinds of dataModels). – Mani Kumar Jun 29 '18 at 06:11
  • I am posting the image of the code. The comparison part will come at "//.." part in the image. – Mani Kumar Jun 29 '18 at 06:15
  • mAppoiuntmentList is of type DataAppointments model (parent), and have two types of children dataModels DataPatientDetails and DataDate. But function getName() and getPhone() are in DataPatientDetails. So how can i do the comparison? Thanks in advance. – Mani Kumar Jun 29 '18 at 06:21
  • you can use `instanceof` keyword to check if model is of type `DataPatientDetails`. Then cast it and compare name or phone_no against the search string. – Binary Baba Jun 29 '18 at 06:25
  • If you can help me in code it would be appreciated.@RickSanchez :) – Mani Kumar Jun 29 '18 at 06:28
  • Please copy the code in the question, it's will be easier that way. Thanks. – Binary Baba Jun 29 '18 at 06:59
  • 1
    Have pasted the code. :) – Mani Kumar Jun 29 '18 at 07:05

2 Answers2

0

Search is not depends upon view, it is depend upon data. Apply filer upon your list according to your criteria and differentiate your view with viewType.

Shiv Jalkote
  • 111
  • 6
0

Based on the code you posted.

in the else statement, I am not exactly sure what is being compared. You can have condition to check if DataAppointments is of type DataPatientDetails and then do your comparision. I am assuming mAppointmentsList is an actual list of data.

else {
 for (DataAppointments data : mAppointmentsList) {
  if (data instanceof DataPatientDetails) {
    DataPatientDetails details = (DataPatientDetails) data;
    // do your comparision here, if it passes, then add to the filtered results
  }
 }
}
Binary Baba
  • 1,953
  • 2
  • 16
  • 23
  • Can you tell me where i am getting it wrong. I think its in `publishResults` function. I am posting image at the end of my asked question. – Mani Kumar Jun 29 '18 at 06:55
  • Are you getting the proper values in the logs for the filtered data? and are you using `mAppointmentsListFiltered` as your actual dataset in the `recyclerView`? – Binary Baba Jun 29 '18 at 07:04
  • yes i am getting right values in the log for filtered results. But it do not filter simultaneously when we type. but when i click back button of phone it gives me the result. After which whole Adapter is cleared don't know how and have to create activity again to fetch data again. – Mani Kumar Jun 29 '18 at 07:08
  • This is the link of the video what my problem actually is. [link] (https://drive.google.com/open?id=1ehuhV6NVTNUp9wlPtslJ8GtHr_WGZ6Cd) – Mani Kumar Jun 29 '18 at 07:17
  • You will need to implement `TextWatcher` to achieve live update as you type. Refer this https://stackoverflow.com/questions/8543449/how-to-use-the-textwatcher-class-in-android – Binary Baba Jun 29 '18 at 07:28
  • I am using onQueryChange listener. code i am posting in the question. Please see it also. – Mani Kumar Jun 29 '18 at 07:30
  • Moreover the same code works fine with homogeneous recylerView. – Mani Kumar Jun 29 '18 at 07:33
  • And also .addTextChange listener cannot to applied to material Search view i am using. @Rick – Mani Kumar Jun 29 '18 at 07:36
  • Try to debug using a breakpoint, to check if on every letter typed, `onQueryChange` listener is called and eventually the filter method. – Binary Baba Jun 29 '18 at 07:38
  • Here is the log ` performFilteringPatientListFiltered: [com.rethinkux.myappointments.data.DataPatientDetails@8b8c547] performFilteringResultsUpcoming: 1 06-29 13:13:13.683 26113-27203/com.rethinkux.myappointments D/UpcomingAppointmentsRvAdapter: Filter Called 06-29 13:13:13.735 26113-27204/com.rethinkux.myappointments D/UpcomingAppointmentsRvAdapter: Filter Called performFiltering: Mohit Nagpal 06-29 13:13:13.792 26113-27206/com.rethinkux.myappointments D/UpcomingAppointmentsRvAdapter: Filter Called performFilteringResultsUpcoming: 3` – Mani Kumar Jun 29 '18 at 07:43
  • It is called on every char i enter. – Mani Kumar Jun 29 '18 at 07:44
  • but i noticed one thing that my Apadpter items are not changing they are remaining constant and are not updating. @Rick can you tell me why? – Mani Kumar Jun 29 '18 at 09:15
  • is this not your adapter list items `mAppointmentsListFiltered`? – Binary Baba Jun 29 '18 at 09:17
  • It is. but i don't know why its not updating. – Mani Kumar Jun 29 '18 at 09:23
  • Check once what is being passed in `publishResults` method. Because that's where `mAppointmentsListFiltered` is being updated. And make sure no where else `mAppointmentsListFiltered' is getting updated. – Binary Baba Jun 29 '18 at 09:25
  • seen it. The same thing works fine in other fragment with homogeneous items. – Mani Kumar Jun 29 '18 at 09:29
  • `mAdapter.getItemCount` always gives us total number of items not filtered in both `onQueryTextSubmit` and `onQueryTextChange`. – Mani Kumar Jun 29 '18 at 10:08
  • I figured out in my code when search view is empty, it should be `mAppointmentsListFiltered = mAppointmentList`. After correcting it i got that my Adapter isn't getting updated and search isn't working in both functions either. – Mani Kumar Jun 29 '18 at 10:32
  • Problem solved. :) I was returning orignal list always in Adapter's `getItemCount` now when i returned `mAppointmentsFilteredList` it works fine now. Thanks by the way for your response :) – Mani Kumar Jun 29 '18 at 11:35
  • Doesn't this answer solves your first problem related to filtering data of 2 different modals? If it does, please mark this as correct answer. Always happy to help :) Thanks. – Binary Baba Jun 29 '18 at 13:03