Search code examples
androidrealm

How to filter the data in realm adapter?


I am facing the issue in filtering the data in the realm adapter. I am creating the searchview to search data by filtering the data in realm adapter.

My code for searchview implementation is

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

        final MenuItem item = menu.findItem(R.id.action_search);
        final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
        Log.e("Filter ","Filtering");
        searchView.setOnQueryTextListener(this);

        MenuItemCompat.setOnActionExpandListener(item,
                new MenuItemCompat.OnActionExpandListener() {
                    @Override
                    public boolean onMenuItemActionCollapse(MenuItem item) {
// Do something when collapsed
                        adapter.setFilter(realmPhonecallList);

                        Log.e("Filter 1","Filtering");
                        return true; // Return true to collapse action view
                    }

                    @Override
                    public boolean onMenuItemActionExpand(MenuItem item) {
// Do something when expanded
                        return true; // Return true to expand action view
                    }
                });
    }



    @Override
    public boolean onQueryTextSubmit(String newText) {

        return true;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        final List<RealmPhoneCallLogs> filteredModelList = filter(realmPhonecallList, newText);
        Log.e("Filter 2","Filtering" + newText);
        adapter.setFilter(filteredModelList);
        Log.e("Filter 3","Filtering" + filteredModelList);
        return true;
    }

    private List<RealmPhoneCallLogs> filter(List<RealmPhoneCallLogs> models, String query) {
        query = query.toLowerCase();

        final List<RealmPhoneCallLogs> filteredModelList = new ArrayList<>();
        for (RealmPhoneCallLogs model : models) {
            final String text = model.getNumber().toLowerCase();
            if (text.contains(query)) {
                filteredModelList.add(model);
            }
        }
        Log.e("Filter 4","Filtering" + filteredModelList);
        return filteredModelList;
    }

My realm adapter implementation is

private class MyNamesAdapter extends RealmBaseAdapter<RealmPhoneCallLogs> {

    List<RealmPhoneCallLogs> filter;

    public MyNamesAdapter(OrderedRealmCollection<RealmPhoneCallLogs> data) {
        super(data);
        this.filter = data;
    }

    public class ViewHolder {
        TextView number;
        TextView callType;
        TextView startTime;
        TextView contactName;
        TextView callDuration;
        TextView fileSize;
        ImageView contactPhoto;
        ImageView callSymbol;
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final RealmPhoneCallLogs realmPhoneCallLogs = getItem(position);
        ViewHolder viewHolder;
        if (convertView == null) {
            viewHolder = new ViewHolder();
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(R.layout.calllog_layout, parent, false);
            viewHolder.number = (TextView) convertView.findViewById(R.id.missedNumber);
            viewHolder.startTime = (TextView) convertView.findViewById(R.id.missedStartTime);
            viewHolder.contactName = (TextView) convertView.findViewById(R.id.missedContactName);
            viewHolder.callDuration = (TextView) convertView.findViewById(R.id.missedCallDuration);
            viewHolder.fileSize = (TextView) convertView.findViewById(R.id.missedFileSize);
            viewHolder.contactPhoto = (ImageView) convertView.findViewById(R.id.missedImage);
            viewHolder.callSymbol = (ImageView) convertView.findViewById(R.id.callSymbol);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        if (adapterData != null) {
            viewHolder.number.setText(realmPhoneCallLogs.getNumber());
            viewHolder.contactName.setText(getContactName(realmPhoneCallLogs.getNumber()));
            viewHolder.callDuration.setText(getTime(realmPhoneCallLogs.getCallDuration()));
            viewHolder.startTime.setText(realmPhoneCallLogs.getStartTime());
            viewHolder.contactPhoto.setImageBitmap(getContactsImage(realmPhoneCallLogs.getNumber()));
            String path = new String(Environment.getExternalStorageDirectory() + "/NewCallLogs/" + realmPhoneCallLogs.getCallRecords());
            File file = new File(path);
            String size;

            long filesize = file.length();
            long fileSizeInKB = filesize / 1024;
            long fileSizeInMB = fileSizeInKB / 1024;
            if(fileSizeInKB >=1024){
                 size= fileSizeInMB + " Mb";
            }else {
                 size = fileSizeInKB + " Kb";
            }
            if(!size.isEmpty()){
                viewHolder.fileSize.setText(size);
            }else{
                viewHolder.fileSize.setText(0);
            }



            if (realmPhoneCallLogs.getCallType().equals("I")) {
                viewHolder.callSymbol.setImageResource(R.mipmap.call_received);
            } else if (realmPhoneCallLogs.getCallType().equals("O")) {
                viewHolder.callSymbol.setImageResource(R.mipmap.call_made);
            } else if (realmPhoneCallLogs.getCallStatus().equals("UA")) {
                viewHolder.callSymbol.setImageResource(R.mipmap.call_missed);
            }

            return convertView;
        }
        return convertView;
    }

    public void setFilter( List<RealmPhoneCallLogs> filtedData) {
        filter = new ArrayList<>();
        filter.addAll(filtedData);
        notifyDataSetChanged();
    }
}

Please help me how to filter the data in realm.


Solution

  • public void setFilter( List<RealmPhoneCallLogs> filtedData) {
        filter = new ArrayList<>(); // <-- WRONG
        filter.addAll(filtedData); // <-- WRONG
    
    private List<RealmPhoneCallLogs> filter(List<RealmPhoneCallLogs> models, String query) {
        query = query.toLowerCase();
    
        final List<RealmPhoneCallLogs> filteredModelList = new ArrayList<>(); // <-- WRONG
        for (RealmPhoneCallLogs model : models) { // <-- WRONG
            final String text = model.getNumber().toLowerCase();
            if (text.contains(query)) { // <-- WRONG: should be Realm query
    

    Instead, you need to do

    // from https://stackoverflow.com/a/33818311/2413303
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                adapter.getFilter().filter(query);
                return false;
            }
    
            @Override
            public boolean onQueryTextChange(String newText) {
                if (searchView.getQuery().length() == 0) {
                     adapter.getFilter().filter("");
                }
                return false;
            }
    });
    

    Then just like in the linked answer

    private class MyNamesAdapter
            extends RealmBaseAdapter<RealmPhoneCallLogs> 
            implements Filterable {
        public MyNamesAdapter(OrderedRealmCollection<RealmPhoneCallLogs> data) {
            super(data);
        }
    
        public class ViewHolder {
            TextView number;
            TextView callType;
            TextView startTime;
            TextView contactName;
            TextView callDuration;
            TextView fileSize;
            ImageView contactPhoto;
            ImageView callSymbol;
        }
    
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final RealmPhoneCallLogs realmPhoneCallLogs = getItem(position);
            ViewHolder viewHolder;
            if(convertView == null) {
                viewHolder = new ViewHolder();
                LayoutInflater inflater = LayoutInflater.from(getContext());
                convertView = inflater.inflate(R.layout.calllog_layout, parent, false);
                viewHolder.number = (TextView) convertView.findViewById(R.id.missedNumber);
                viewHolder.startTime = (TextView) convertView.findViewById(R.id.missedStartTime);
                viewHolder.contactName = (TextView) convertView.findViewById(R.id.missedContactName);
                viewHolder.callDuration = (TextView) convertView.findViewById(R.id.missedCallDuration);
                viewHolder.fileSize = (TextView) convertView.findViewById(R.id.missedFileSize);
                viewHolder.contactPhoto = (ImageView) convertView.findViewById(R.id.missedImage);
                viewHolder.callSymbol = (ImageView) convertView.findViewById(R.id.callSymbol);
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }
    
            if(adapterData != null) {
                viewHolder.number.setText(realmPhoneCallLogs.getNumber());
                viewHolder.contactName.setText(getContactName(realmPhoneCallLogs.getNumber()));
                viewHolder.callDuration.setText(getTime(realmPhoneCallLogs.getCallDuration()));
                viewHolder.startTime.setText(realmPhoneCallLogs.getStartTime());
                viewHolder.contactPhoto.setImageBitmap(getContactsImage(realmPhoneCallLogs.getNumber()));
                String path = new String(Environment.getExternalStorageDirectory() + "/NewCallLogs/" + realmPhoneCallLogs
                        .getCallRecords());
                File file = new File(path);
                String size;
    
                long filesize = file.length();
                long fileSizeInKB = filesize / 1024;
                long fileSizeInMB = fileSizeInKB / 1024;
                if(fileSizeInKB >= 1024) {
                    size = fileSizeInMB + " Mb";
                } else {
                    size = fileSizeInKB + " Kb";
                }
                if(!size.isEmpty()) {
                    viewHolder.fileSize.setText(size);
                } else {
                    viewHolder.fileSize.setText(0);
                }
    
                if("I".equals(realmPhoneCallLogs.getCallType())) {
                    viewHolder.callSymbol.setImageResource(R.mipmap.call_received);
                } else if("O".equals(realmPhoneCallLogs.getCallType())) {
                    viewHolder.callSymbol.setImageResource(R.mipmap.call_made);
                } else if("UA".equals(realmPhoneCallLogs.getCallStatus())) {
                    viewHolder.callSymbol.setImageResource(R.mipmap.call_missed);
                }
    
                return convertView;
            }
            return convertView;
        }
    
    // filtering
        public void filterResults(String text) {
            text = text == null ? null : text.toLowerCase().trim();
            if(text == null || "".equals(text)) {
                updateData(realm.where(RealmPhoneCallLogs.class).findAllSorted("id");
            } else {
                updateData(realm.where(RealmPhoneCallLogs.class)
                                    .contains("number", text, Case.INSENSITIVE)
                                    .findAllSorted("id")); 
            }
        }
    
        public Filter getFilter() {
            return new MyNamesFilter(this);
        }
    
        private class MyNamesFilter
                extends Filter {
            private final MyNamesAdapter adapter;
    
            private MyNamesFilter(MyNamesAdapter adapter) {
                super();
                this.adapter = adapter;
            }
    
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                return new FilterResults();
            }
    
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                adapter.filterResults(constraint.toString());
            }
        }
    }
    

    For filtering Realm, you can also check out the official documentation on queries.