Решение ArrayIndexOutOfBoundsException при восстановлении состояния RecyclerView с ArrayList пользовательских объектов и Gson - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть RecyclerView, в котором представления / данные в ViewHolder s (изображение, заголовок, описание) извлекаются с помощью методов получения пользовательского объекта Challenge.

Я такжеу меня есть ArrayList типа Challenge (ArrayList<Challenge> mChallenges), в который я добавляю все вызовы, а позже передаю этот ArrayList в качестве параметра моего подкласса RecyclerView.Adapter при его инициализации.

* ViewHolder sиз моего RecyclerView также есть флажок, чтобы пользователи могли выбирать задачи, которые они хотят, и эти выбранные задачи сохраняются в другом ArrayList<Challenge> с именем currentSelectedChallenges.Вот как они добавляются.

@Override
    public void onChallengeChecked(int position) {   // method of interface

    if (!currentSelectedChallenges.contains(mChallenges.get(position))){        
         currentSelectedChallenges.add(mChallenges.get(position));
    }
}

Когда пользователь оставляет фрагмент, в котором содержится RecyclerView, либо с помощью кнопки «Назад», либо при закрытии приложения, я сохраняю выбранные испытания ArrayList<Challenge> currentSelectedChallenges с SharedPreferences с использованием Gson, например:

@Override
public void onPause() {
    super.onPause();

    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);

    SharedPreferences.Editor editor = sharedPreferences.edit();

    Gson gson = new Gson();

    Type type = new TypeToken<ArrayList<Challenge>>(){}.getType();

    String json = gson.toJson(currentSelectedChallenges, type);

    editor.putString("selected challenges", json);

    editor.apply();
}

И я восстанавливаю currentSelectedChallenges в методе onRestore фрагмента следующим образом:

@Override
public void onResume() {
    super.onResume();

    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);

    Gson gson = new Gson();

    String json = sharedPreferences.getString("selected challenges", null);

    Type type = new TypeToken<ArrayList<Challenge>>() {
    }.getType();

    currentSelectedChallenges = gson.fromJson(json, type);


    if (currentSelectedChallenges == null) {

        currentSelectedChallenges = new ArrayList<>();

    } else
    {

        for (int i = 0; i < currentSelectedChallenges.size(); i++) {

            int index = mChallenges.indexOf(currentSelectedChallenges.get(i));

            mChallenges.get(index).setChecked(true);

        }

        mChallengesAdapter.notifyDataSetChanged();


    }
}

Когда я пытаюсь восстановить проверенное состояние CheckBox в ViewHolder, я получаю ArrayIndexOutOfBoundsExceptions потому что currentSelectedChallenges.get(i) не найден внутри mChallenges, поэтому он возвращает -1.Я зарегистрировал проблемы и объекты имеют разные идентификаторы, хотя я могу использовать методы установки и получу те же данные.

Я пытался обмануть Android и использовал это:

    for (int i=0; i < currentSelectedChallenges.size(); i++) {         

                    for (Challenge challenge : mChallenges) {                                           


                        if (challenge.getName().equals(currentSelectedChallenges.get(i).getName())){        

                            challenge.setChecked(true);     
                        }
                    }
mChallengesAdapter.notifyDataSetChanged();

И это действительно помечает в пользовательском интерфейсе проблемы, которые были проверены пользователем, но затем, когда я снова нажимаю на CheckBox, он не обнаруживает мой щелчок, поэтому я знаю, что это неправильное решение.

Может кто-нибудьобъясните, как я должен решить это правильно?

1 Ответ

0 голосов
/ 22 февраля 2019
mChallenges.indexOf(currentSelectedChallenges.get(i)) 

возвращает -1, потому что сравнивает ссылку вместо ваших заинтересованных данных.Вы должны переопределить equals и hashCode из Challenge класса:

class Challenge{

// your current code

   @Override
    public boolean equals(Object o) {

        if (o == this) return true;
        if (!(o instanceof Challenge)) {
            return false;
        }

        Challenge challenge = (Challenge) o;

        return challenge.name.equals(name) /*&& compare other values for equality*/;
        // also check for null name if it is necessary 
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + name.hashCode();
        //result = 31 * result + age; // other property
        //result = 31 * result + passport.hashCode();// other property
        return result;
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...