Я пытаюсь обновить элементы recycleview с помощью notifyDataSetChanged ().
Это мой метод onBindViewHolder () в адаптере recycleview.
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
//checkbox view listener
viewHolder.getCheckbox().setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//update list items
notifyDataSetChanged();
}
});
}
Что я хочу сделать, так это обновить элементы списка после того, как я поставлю флажок. Однако я получаю незаконное исключение:"Cannot call this method while RecyclerView is computing a layout or scrolling"
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
at android.support.v7.widget.RecyclerView.assertNotInLayoutOrScroll(RecyclerView.java:1462)
at android.support.v7.widget.RecyclerView$RecyclerViewDataObserver.onChanged(RecyclerView.java:2982)
at android.support.v7.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:7493)
at android.support.v7.widget.RecyclerView$Adapter.notifyDataSetChanged(RecyclerView.java:4338)
at com.app.myapp.screens.RecycleAdapter.onRowSelect(RecycleAdapter.java:111)
Я также использовал notifyItemChanged (), то же исключение. Есть ли секретный способ обновления, чтобы уведомить адаптер, что что-то изменилось?
Ответы:
Вам следует переместить метод setOnCheckedChangeListener () в ViewHolder, который является внутренним классом вашего адаптера.
onBindViewHolder()
это не метод инициализацииViewHolder
. Этот метод является этапом обновления каждого элемента ресайклера. Когда вы звонитеnotifyDataSetChanged()
,onBindViewHolder()
будет называться количество раз каждого элемента.Итак, если вы
notifyDataSetChanged()
поместитеonCheckChanged()
и инициализируете checkBoxonBindViewHolder()
, вы получите исключение IllegalStateException из-за циклического вызова метода.установите флажок -> onCheckedChanged () -> notifyDataSetChanged () -> onBindViewHolder () -> установите флажок -> onChecked ...
Просто вы можете исправить это, поставив один флаг в Adapter.
попробуй это,
источник
AdapterViewObserver
пока выполняетсяonBindViewHolder()
.Вы можете просто сбросить предыдущий прослушиватель, прежде чем вносить изменения, и вы не получите этого исключения.
источник
Использование a
Handler
для добавления элементов и звонковnotify...()
с этого местаHandler
решило проблему для меня.источник
Я плохо знаю, но у меня тоже была такая же проблема. Я решил эту проблему, используя
onClickListner
наcheckbox
Попробуйте, это может помочь!
источник
источник
Когда у вас есть сообщение об ошибке:
Просто, просто сделайте то, что вызывает исключение в:
источник
Нашел простое решение -
Здесь мы создаем runnable для notifyItemChanged для позиции, когда recyclerview готов обработать ее.
источник
ваш элемент CheckBox изменяется при вызове,
notifyDataSetChanged();
поэтому возникнет это исключение. Попробуй назватьnotifyDataSetChanged();
в посте твоего мнения. Например:источник
Сначала я подумал, что ответ Moonsoo (принятый ответ) не сработает для меня, потому что я не могу инициализировать свой
setOnCheckedChangeListener()
в конструкторе ViewHolder, потому что мне нужно каждый раз связывать его, чтобы он получал обновленную переменную позиции. Но мне потребовалось много времени, чтобы понять, о чем он говорит.Вот пример "кругового вызова метода", о котором он говорит:
Единственная проблема с этим заключается в том, что когда нам нужно инициализировать переключатель, чтобы он был включен или выключен (например, из прошлого сохраненного состояния), он вызывает слушателя, который может вызвать,
nofityItemRangeChanged
который вызываетonBindViewHolder
снова. Вы не можете позвонить,onBindViewHolder
когда вы уже находитесь вonBindViewHolder
], потому что вы не можете,notifyItemRangeChanged
если вы уже в середине уведомления об изменении диапазона элементов. Но мне нужно было только обновить пользовательский интерфейс, чтобы показать его включенным или выключенным, не желая фактически ничего запускать.Вот решение, которое я узнал из ответа JoniDS, которое предотвратит бесконечный цикл. Пока мы устанавливаем для слушателя значение «null» до того, как мы устанавливаем Checked, он будет обновлять пользовательский интерфейс, не запуская слушателя, избегая бесконечного цикла. Затем мы можем установить слушателя после.
Код JoniDS:
Полное решение моего примера:
источник
Почему бы не проверить
RecyclerView.isComputingLayout()
состояние следующим образом?источник
Пока элемент связывается диспетчером компоновки, очень вероятно, что вы устанавливаете отмеченное состояние вашего флажка, что вызывает обратный вызов.
Конечно, это предположение, потому что вы не опубликовали полную трассировку стека.
Вы не можете изменить содержимое адаптера, пока RV выполняет пересчет макета. Вы можете избежать этого, не вызывая notifyDataSetChanged, если отмеченное состояние элемента равно значению, отправленному в обратном вызове (что будет иметь место, если вызов
checkbox.setChecked
запускает обратный вызов).источник
Используйте onClickListner для флажка вместо OnCheckedChangeListener, это решит проблему
источник
Прежде чем
notifyDataSetChanged()
просто проверить это с помощью этого метода:recyclerView.IsComputingLayout()
источник
Простое использование сообщения:
источник
Я столкнулся именно с этой проблемой! После того, как ответ Moonsoo на самом деле не помог моей лодке, я немного поработал и нашел решение, которое сработало для меня.
Во-первых, вот часть моего кода:
Вы заметите, что я специально уведомляю адаптер о позиции, которую я меняю, а не обо всем наборе данных, как это делаете вы. При этом, хотя я не могу гарантировать, что это сработает для вас, я решил проблему, заключив свой
notifyItemChanged()
вызов в блок try / catch. Это просто перехватило исключение, но все же позволило моему адаптеру зарегистрировать изменение состояния и обновить отображение!Надеюсь, это кому-то поможет!
РЕДАКТИРОВАТЬ: Я признаю, что это, вероятно, не правильный / зрелый способ решения проблемы, но, поскольку он, похоже, не вызывает каких-либо проблем, оставляя исключение необработанным, я думал, что поделюсь, если это будет хорошо хватит для кого-то еще.
источник
Это происходит потому, что вы, вероятно, устанавливаете «слушателя» до того, как настраиваете значение для этой строки, что заставляет слушателя запускаться, когда вы «настраиваете значение» для флажка.
Что вам нужно сделать:
источник
источник
просто использовать
isPressed()
методCompoundButton
в ,onCheckedChanged(CompoundButton compoundButton, boolean isChecked)
например ,
источник
У меня была такая же проблема с использованием флажка и RadioButton. Замена
notifyDataSetChanged()
наnotifyItemChanged(position)
работала. Я добавил вisChecked
модель данных логическое поле . Затем я обновил логическое значение иonCheckedChangedListener
позвонилnotifyItemChanged(adapterPosition)
. Возможно, это не лучший способ, но у меня сработало. Логическое значение используется для проверки, отмечен ли элемент.источник
в основном это происходит обусловленно notifydatasetchanged вызова onCheckedchanged события флажка , и в этом случае снова там notifydatasetchanged .
чтобы решить эту проблему, вы можете просто проверить, установлен ли флажок программно или пользователем. для этого есть метод isPressed .
поэтому оберните весь код списка внутри метода isPressed. и все готово.
источник
Я мучился с этой проблемой час, и вот как вы можете ее исправить. Но прежде чем вы начнете, для этого решения есть несколько условий.
МОДЕЛЬ КЛАСС
ПРОВЕРКА В КЛАССЕ АДАПТЕРА
КОНСТРУКТОР КЛАССА АДАПТЕРА И ПЕРЕЧЕНЬ МОДЕЛЕЙ
ONBINDVIEW [Пожалуйста, используйте onclick вместо onCheckChange]
}
источник
Для меня проблема возникла, когда я вышел из EditText с помощью Done, Back или внешнего касания ввода. Это приводит к обновлению модели вводимым текстом, а затем обновлению представления ресайклера с помощью наблюдения за данными в реальном времени.
Проблема заключалась в том, что курсор / фокус оставались в EditText.
Когда я удалил фокус, используя:
Метод уведомления об изменении данных в представлении ресайклера перестал выдавать эту ошибку.
Думаю, это одна из возможных причин / решений данной проблемы. Не исключено, что это исключение можно исправить другим способом, так как оно может быть вызвано совершенно другой причиной.
источник