Моя структура такая: в Fragment
я вызываю ViewModel
, который создает экземпляр Adapter
Для каждого пункта моего RecyclerView
у меня есть кнопка, которую я слушаю
binding.addItem.setOnClickListener(onAddItemClicked(product))
private fun onAddToQuoteClicked(product: Product): View.OnClickListener {
return View.OnClickListener {
// TODO add item
}
}
Я не знаю, как отправить данные этого элемента во фрагмент, есть ли способ сделать это?
Должен ли я использовать интерфейс между Adapter
и ViewModel
и между ViewModel
и Fragment
?
Или я могу использовать RxEvent
и RxBus
?
Во-первых, адаптер должен быть создан во фрагменте, и там же должен быть реализован onClickListener. Тогда вам не нужно ничего отправлять из RecyclerView в Fragment. Позже вы можете захотеть иметь общедоступный метод в RecyclerView, который вы вызываете из Fragment при щелчке элемента.
Я имею в виду «отправить данные во фрагмент», мне нужно щелкнуть элемент для отправки в основное действие в качестве результата (выбранный элемент) из фрагмента
Я не создаю экземпляр адаптера во фрагменте, но в ViewModel я использую архитектуру MVVM, и я не знаю, правильно ли это
Вы можете напрямую добавить элемент через ссылку ViewModel и подписаться на изменение RxJava EventBus или LiveData в своем фрагменте или действии.
Как я могу напрямую добавить элемент через ViewModel Reference?
Создайте функцию в ViewModel для обновления данных и вызовите ее.
Сначала для навигации между ViewModel и Fragment -
Во-вторых, для связи между адаптером и фрагментом — вы можете использовать ту же стратегию, что описана выше. В этом случае я рекомендую использовать RxJava, так как обычно вам просто нужно обработать один или несколько прослушивателей кликов (например, для наблюдаемых, которые испускают некоторый объект данных).
Если вам нужны примеры кода, напишите мне в комментариях.
ОБНОВИТЬ — лучше создать экземпляр адаптера в представлении, поскольку я предполагаю, что вы используете шаблон проектирования MVVM (где весь код, связанный с пользовательским интерфейсом, должен находиться в компоненте представления).
Фрагмент примера — связь адаптера Rx — PublishSubject
В вашем Адаптер
private val publisher = PublishSubject.create<Product>()
fun getObservableProductItem(): Observable<Product> = publisher.hide()
binding.addItem.setOnClickListener(onAddItemClicked(product))
private fun onAddToQuoteClicked(product: Product): View.OnClickListener {
return View.OnClickListener {
publisherRideItem.onNext(items[adapterPosition])
}
}
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
publisherRideItem.onComplete()
}
А в вашем Фрагмент
compositeDisposable.add(adapter.getObservableProductItem().subscribe {
//TODO do whatever you want with it
})
override fun onDestroy() {
super.onDestroy()
compositeDisposable.clear()
}
Спасибо за ваш ответ, да, мне нужен пример для связи между адаптером и фрагментом
вы советуете мне использовать RxJava EventBus для связи между адаптером и фрагментом
Он посоветовал вам, что просто использовать интерфейс лучше, чем вводить PublishSubject для этого.
В случае связи между ViewModel и Fragment лучше использовать интерфейс, а между Adapter и Fragment (если у вас есть только 1 или 2 прослушивателя кликов для обработки, я предпочитаю пользователя RxJava).
@GhizlaneLotfi, если этот ответ решит ваши вопросы, проголосуйте и примите его, в противном случае задайте больше вопросов, я постараюсь вам помочь.
RxJava PublishSubject — лучший вариант, я бы предпочел его, и он очень прост.
Я пробовал с recyclerView - Fragment - ViewModel. У некоторых будет listadapter -> recyclerVire -> Fragment -> ViewModel. Я объяснил это ниже.
Список адаптеров
укажите здесь свой PublishSubject
class myapadter : ListAdapter
{
object RxBus {
val itemClickStream: PublishSubject<View> = PublishSubject.create()
}
}
ViewHolder
в вашем viewHolder вызывает этот PublishSubject.
class myViewholder : RecyclerView.ViewHolder(itemView)
{
itemView.myButton.setOnClickListener {
v -> RxBus.itemClickStream.onNext(v) }
}
Фрагмент
подпишитесь на PublishSubject здесь, во фрагменте, это автоматически получит уведомление.
myapadter.RxBus.itemClickStream.subscribe(){ v ->
if (v.id == R.id.myButton) {
viewModel.callyourfunction()
}
не могли бы вы уточнить? Я думаю, вам нужно добавить некоторую логику, и вы добавляете прослушиватель в адаптер. Что вы имеете в виду, говоря «отправить данные во фрагмент»? Что фрагмент должен делать с данными?