Как отсортировать recylerview по наименьшему числу /String android studio

У меня есть recylerview в моем приложении, которое содержит два текстовых изображения, один - rankTextView, а другой - имяTextview. Что-то вроде этого;

введите описание изображения здесь

Что я хочу сделать, так это сортировать этот recylerview, во-первых, в порядке наименьшего номера, и если есть два одинаковых номера, я хочу, чтобы он был отсортирован по строкам. В приведенном выше скриншоте я имею, например, два человека, рейтинг 1, во-первых, я хочу, чтобы recylerview помещал их в начало, а затем сортировал их по String.

Я искал онлайн, чтобы посмотреть, как я могу это сделать, но будучи новичком в android, я не смог поиграть/адаптировать результаты в свой проект. Например:

Как отсортировать строки в Android RecyclerView?

Что такое SortedList <T> работа с RecyclerView.Adapter?

Я создал пользовательский адаптер, содержащий текстовое представление, называемое rankTextview, и другое текстовое представление, называемое nameTextview, например:

 rankTextview = (TextView) itemView.findViewById(R.id.ranktextview);
 nameTextview = (TextView) itemView.findViewById(R.id.nametextview);

то у меня есть метод, который принимает какое значение для ввода в это текстовое представление как параметр, например:

 public addPerson(String rankTextview, String personTextview,) {
        this.rankTextview = rankTextview;
        this.personTextview = personTextview;
    }

а затем я вызываю этот метод в своем основном классе для добавления данных, например:

person.add(new addPerson
        ("1\nrank", "James Kub"));
person.add(new addPerson
        ("2\nrank", "Peter Hanly"));
person.add(new addPerson
        ("3\nrank", "Josh Penny"));
person.add(new addPerson
        ("1\nrank", "Danny Jackson"));
person.add(new addPerson
        ("3\nrank", "Brad Black"));

Теперь то, что я хочу сделать, это отсортировать эти данные сначала по порядку наименьшего номера рангов, например, 1, 2,3... и если есть два одинаковых числа, тогда я хочу отсортировать по имени в алфавитном порядке. Кроме того, в будущем мое приложение будет содержать очки вместо рангов, которые будут такими десятичными числами, как это. 1.1, 1.5, 1.1, 2.1, 2.5 и т.д., Поэтому можно было бы считать число десятичных чисел при сортировке по рангу.

Спасибо заранее, и, пожалуйста, дайте мне знать, если мой вопрос недостаточно ясен. Кроме того, поскольку у меня было так много строк кода, я не был уверен, какой раздел предоставить и который не предоставлять, пожалуйста, сообщите мне, есть ли какой-либо код, который у меня отсутствует, который я должен был включить.

Редакция:

public void animateTo(List<ExampleModel> models) {
        applyAndAnimateRemovals(models);
        applyAndAnimateAdditions(models);
        applyAndAnimateMovedItems(models);
    }

    private void applyAndAnimateRemovals(List<ExampleModel> newModels) {
        for (int i = mModels.size() - 1; i >= 0; i--) {
            final ExampleModel model = mModels.get(i);
            if (!newModels.contains(model)) {
                removeItem(i);
            }
        }
    }

    private void applyAndAnimateAdditions(List<ExampleModel> newModels) {
        for (int i = 0, count = newModels.size(); i < count; i++) {
            final ExampleModel model = newModels.get(i);
            if (!mModels.contains(model)) { // error here, saying cannot resolve method contains
                addItem(i, model);
            }
        }
    }

    private void applyAndAnimateMovedItems(List<ExampleModel> newModels) {
        for (int toPosition = newModels.size() - 1; toPosition >= 0; toPosition--) {
            final ExampleModel model = newModels.get(toPosition);
            final int fromPosition = mModels.indexOf(model);
            if (fromPosition >= 0 && fromPosition != toPosition) {
                moveItem(fromPosition, toPosition);
            }
        }
    }

    public ExampleModel removeItem(int position) {
        final ExampleModel model = mModels.remove(position); // Error here, saying in sortedlist cannot be applied to (int)
        notifyItemRemoved(position);
        return model;
    }

    public void addItem(int position, ExampleModel model) {
        mModels.add(position, model); // Error here, saying add has private access in 'android.support.v7.util.SortedList'
        notifyItemInserted(position);
    }

    public void moveItem(int fromPosition, int toPosition) {
        final ExampleModel model = mModels.remove(fromPosition); // Error here, saying in sortedlist cannot be applied to (int)
        mModels.add(toPosition, model); // Error here, saying add has private access in 'android.support.v7.util.SortedList'
        notifyItemMoved(fromPosition, toPosition);
    }

Ответы

Ответ 1

Есть несколько вариантов реализации сортировки в RecyclerView. Конечно, можно полагаться на интерфейсы Comparable<T> и Comparator<T>, но, как вы упомянули, также возможно использовать класс SortedList<T>, определенный в Android SDK.

Назначение SortedList<T> упрощает сортировку элементов в RecyclerView, что позволяет перехватить значимые события, такие как "добавленный новый элемент", "элемент удален" и т.д.

В вашем случае вы можете действовать следующим образом:

  • Определите класс Person для обертывания ранга и имени. Обратите внимание, что в этой версии я предполагаю иметь целочисленные значения для ранга, но довольно легко перейти к десятичному значению.

    class Person {
    
        private String rank;
        private String name;
    
        public Person(String rank, String name) {
            this.rank = rank;
            this.name = name;
        }
    
        // getters and setters here
    
    }
    
  • Определите, где будет строиться RecyclerView и соответствующий адаптер. В этом примере я включил FloatingActionButton для вставки новых случайных лиц. Как вы можете видеть, при создании нового Person на адаптере вызывается метод addPerson. Его эффект будет состоять в том, чтобы обновить RecyclerView, отсортировав его в соответствии с критериями, определенными в самом адаптере (см. Пункт 3).

    public class SortPersonsActivity extends AppCompatActivity {
    
        private List<Person> mPersons;
    
        private SortPersonsAdapter mPersonsAdapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_persons_list);
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
    
            mPersons = new ArrayList<>();
            mPersons.add(new Person("1\nrank", "James Kub"));
            mPersons.add(new Person("2\nrank", "Peter Hanly"));
            mPersons.add(new Person("3\nrank", "Josh Penny"));
            mPersons.add(new Person("1\nrank", "Danny Jackson"));
            mPersons.add(new Person("3\nrank", "Brad Black"));
    
            RecyclerView recyclerView = (RecyclerView) findViewById(R.id.lst_items);
            recyclerView.setLayoutManager(getLayoutManager());
            mPersonsAdapter = new SortPersonsAdapter(this, mPersons);
            recyclerView.setAdapter(mPersonsAdapter);
    
            FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // building new fake person
                    Person person = new Person(
                            buildRandomInt(10) + "\nrank",
                            buildRandomName(5) + " " + buildRandomName(5));
                    // let keep also basic list updated
                    mPersons.add(person);
                    // let update adapter
                    mPersonsAdapter.addPerson(person);
                }
            });
        }
    
        private RecyclerView.LayoutManager getLayoutManager() {
            LinearLayoutManager llm = new LinearLayoutManager(this);
            llm.setOrientation(LinearLayoutManager.VERTICAL);
            return llm;
        }
    
        // support method for random names and ranks here
    
    }
    
  • Внедрите адаптер RecyclerView, используя SortedList<Person>. Здесь важно заметить, что все Лики вставляются в SortedList<Person>. Для создания SortedList<T> требуется определить Callback для перехвата событий, а также для определения критериев сортировки. В нашем случае, как вы можете видеть, метод compare определяет критерии сортировки лиц, тогда как метод onInserted определяет, что делать, когда новый человек вставлен (в этом случае уведомлять об изменении набора данных для обновления RecyclerView). Обратите внимание также на реализацию метода addPerson, описанного в пункте 2. Он просто добавляет Person в SortedList, потому что логика обновления RecyclerView встроена в упомянутый ранее метод Callback onInserted.

    class SortPersonsAdapter extends RecyclerView.Adapter<SortPersonsAdapter.PersonViewHolder> {
    
        protected static class PersonViewHolder extends RecyclerView.ViewHolder {
    
            View layout;
            TextView txt_rank;
            TextView txt_full_name;
    
            public PersonViewHolder(View itemView) {
                super(itemView);
                layout = itemView;
                txt_rank = (TextView) itemView.findViewById(R.id.txt_rank);
                txt_full_name = (TextView) itemView.findViewById(R.id.txt_full_name);
            }
    
        }
    
        private Context mContext;
        private LayoutInflater mLayoutInflater;
    
        private SortedList<Person> mPersons;
    
        public SortPersonsAdapter(Context context, List<Person> persons) {
            mContext = context;
            mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            mPersons = new SortedList<>(Person.class, new PersonListCallback());
            mPersons.addAll(persons);
        }
    
        public void addPerson(Person person) {
            mPersons.add(person);
        }
    
        @Override
        public int getItemCount() {
            return mPersons.size();
        }
    
        @Override
        public SortPersonsAdapter.PersonViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View itemView = mLayoutInflater.inflate(R.layout.view_person_item, parent, false);
            return new PersonViewHolder(itemView);
        }
    
        @Override
        public void onBindViewHolder(final PersonViewHolder viewHolder, final int position) {
            Person person = mPersons.get(position);
            viewHolder.txt_rank.setText(person.getRank());
            viewHolder.txt_full_name.setText(person.getName());
        }
    
        /**
         * Implementation of callback for getting updates on person list changes.
         */
        private class PersonListCallback extends SortedList.Callback<Person> {
    
            @Override
            public int compare(Person p1, Person p2) {
                String[] rank1 = p1.getStringRank().split("\n");
                String[] rank2 = p2.getStringRank().split("\n");
                int diff = Integer.parseInt(rank1[0]) - Integer.parseInt(rank2[0]);
                return (diff == 0) ? p1.getName().compareTo(p2.getName()) : diff;
            }
    
            @Override
            public void onInserted(int position, int count) {
                notifyItemInserted(position);
            }
    
            @Override
            public void onRemoved(int position, int count) {
                notifyItemRemoved(position);
            }
    
            @Override
            public void onMoved(int fromPosition, int toPosition) {
            }
    
            @Override
            public void onChanged(int position, int count) {
            }
    
            @Override
            public boolean areContentsTheSame(Person oldItem, Person newItem) {
                return false;
            }
    
            @Override
            public boolean areItemsTheSame(Person item1, Person item2) {
                return false;
            }
    
        }
    
    }
    

Надеюсь, это поможет. Здесь Я поставил реализацию для вашего RecyclerView, если вам нужна дополнительная информация о коде.

Ответ 2

public int compare(Person p1, Person p2) {
   if(p1.getRank() == p2.getRank()){
      return p1.getName().compareTo(p2.getName());
   }else if(p1.getRank() > p2.getRank()){
      return 1;
   }else{
      return -1;
   }
}  

Сортировка зависит от результата сравнения. Вам нужно вернуть -1, 0 или 1. В фрагменте кода все, что я делаю, это проверка рангов в первую очередь. Если они имеют одинаковый ранг, я сравниваю их имена, которые String, и каждый String имеет compareTo( ), который лексикографически сравнивает две строки.

Если нет, мы просто сортируем их по рангу.

Вы можете упростить свой метод compare( ), добавив в свой класс Person интерфейс Comparable. Это позволит вам использовать Collections фэнтези-фреймы из коробки.