Сохранение выделенного текста RadioButton в классе модели из пункта повторного просмотра - PullRequest
0 голосов
/ 26 октября 2018

Из элемента RecyclerView я пытаюсь сохранить выбранный текст RadioButton в классе модели. Когда я выбираю RadioButton из 1-го элемента, его текст сохраняется соответствующим образом. Проблема в том, что текст RadioButton в той же позиции, что и 8-й элемент, также автоматически сохраняется. Если я выберу радиокнопку из 2-го элемента, текст из 9-го элемента также будет автоматически сохранен и т. Д. Как решить эту проблему?

Метод onBindViewHolder приведен ниже:

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {

    ...

    holder.radioGroup.setTag(position);
    holder.radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {

            int radioButtonID = group.getCheckedRadioButtonId();
            RadioButton radioButton = (RadioButton) group.findViewById(radioButtonID);
            int clickedPos = (Integer) group.getTag();
            models.get(clickedPos).setChecked(radioButtonID);

            if (radioButtonID > 0){
                models.get(clickedPos).setSelectedAns(radioButton.getText().toString());
            }

        }
    });
    holder.radioGroup.check(models.get(position).getChecked());
    Log.d("TAG", "At position " + position + " selected : " + models.get(position).getSelectedAns());

}

1 Ответ

0 голосов
/ 27 октября 2018

Проблема в том, что хотя на первый взгляд код выглядит правильно, на самом деле происходит то, что когда вы вызываете holder.radioGroup.check(), он запускает ваш onCheckedChanged() обработчик событий точно так же, как если бы пользователь его инициировал.

Поскольку виды перерабатываются, вид в позиции 0 повторно используется для позиции 8 в списке.Таким образом, вызов check() в onBindViewHolder() вызовет onCheckedChanged(), с проверенным переключателем из позиции 0, все еще проверенным (то есть checkedId и radioGroup. getCheckedRadioButtonId() вернут идентификатор радиокнопки, проверенной, когда представление использовалось впозиция 0).

Реальная суть заключается в следующем

models.get(clickedPos).setChecked(radioButtonID);

Рассмотрите первые абзацы ответа, и вы поймете, что это (неправильно) обновит элемент модели в позиции 8с radioButtonID, который был проверен, когда это представление использовалось в позиции 0.

Один из способов решить эту проблему - провести различие между изменением, инициированным пользователем, и изменением, инициированным привязкой.Например, вы можете сделать это, добавив поле к ViewHolder, чтобы указать, является ли представление в настоящее время обязательным.

class ViewHolder extends RecyclerView.ViewHolder{
    TextView selectedAnswer;
    RadioGroup radioGroup;

    boolean isBinding;

    ViewHolder(View itemView) {
        super(itemView);

        radioGroup = itemView.findViewById(R.id.radioGroup);

        radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                int position = getAdapterPosition();

                RadioButton radioButton = (RadioButton) group.findViewById(checkedId);

                /* Only update the model when onCheckedChange() was initiated by the user clicking
                   a radio button, not when the adapter is binding the view. In that scenario, we
                   are only interested in passing information FROM the model TO the view. */
                if( !isBinding ) {
                    models.get(position).setChecked(checkedId);
                    models.get(position).setSelectedAns(radioButton != null ? radioButton.getText().toString() : "");
                }

                selectedAnswer.setText(  models.get(position).getSelectedAns() );
            }
        });

        ...
    }
}

@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
    holder.isBinding = true;

    ...

    /* When calling check() here, we invoke onCheckedChanged(), which will
       update the textview that displays the selected answer - so no need to call
           holder.selectedAnswer.setText(  models.get(position).getSelectedAns() )
       from here */
    holder.radioGroup.check(models.get(position).getChecked());

    holder.isBinding = false;
}
...