Как запустить аргумент (объект) в DialogFragment, который открывается через coroutines EventChannel?
Мне нужно, чтобы при долгом нажатии на recycler Item возникал диалог в посросом "уверены что удалить ...?" И после нажатия positiveButton объект Spend() удалялся из базы. Не пойму, как запустить в этот диалог объект, чтобы именно его удаление вызвать.
DoaligFragment:
@AndroidEntryPoint
class DeleteTransactionDialogFragment : DialogFragment() {
private val viewModel: DeleteTransactionViewModel by viewModels()
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
AlertDialog.Builder(requireContext())
.setTitle(requireContext().resources.getString(R.string.confirm_deletion))
.setMessage(requireContext().resources.getString(R.string.really_delete_transaction))
.setNegativeButton(requireContext().resources.getString(R.string.cancel_action), null)
.setPositiveButton(requireContext().resources.getString(R.string.yes)) { _, _ ->
viewModel.onConfirmClick(spend) // here I need to pass Spend() argument but how do I recieve it in the Fragment itself?
}
.create()
}
ViewModel:
@HiltViewModel
class DeleteTransactionViewModel @Inject constructor(
private val repo: FinRepository,
@ApplicationScope private val applicationScope: CoroutineScope
) : ViewModel() {
fun onConfirmClick(spend: Spend) = applicationScope.launch {
repo.deleteSpend(spend)
}
}
RecyclerFragment:
@AndroidEntryPoint
class RecyclerTransactionsFragment : Fragment(R.layout.fragment_transactions_recycler),
RecyclerTransactionAdapter.OnItemClickListener {
private lateinit var binding: FragmentTransactionsRecyclerBinding
private val viewModel: RecyclerTransactionsViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
//blablabla
}
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
viewModel.recTransEvent.collect {
when (it) {
is RecyclerTransactionsViewModel.RecTransEvent.NavigateToDeleteTransactionScreen -> TODO()
}.exhaustive
}
}
}
override fun onItemLongClick(spend: Spend) {
viewModel.onTransactionLongTouched(spend)
}
}
In RecyclerViewModel:
ViewModel() {
private val recTransEventChannel = Channel<RecTransEvent>()
val recTransEvent = recTransEventChannel.receiveAsFlow()
//blablabla
fun onTransactionLongTouched(spend: Spend) = viewModelScope.launch {
recTransEventChannel.send(RecTransEvent.NavigateToDeleteTransactionScreen(spend))
}
sealed class RecTransEvent {
data class NavigateToDeleteTransactionScreen(val spend: Spend) : RecTransEvent()
}
}
Ответы (1 шт):
Нашел решение, отвечу сам, вдруг кому пригодится.
В файле навигации nav_graph.xml (у меня библиотека navigation components) я добавил свой DeleteTransactionDialogFragment в качестве new destination, и к нему добавил в arguments объект Spend() (который является @Parcelable).
И добавил к фрагменту global atcion чтобы можно было на него направлять навигацию.
И в основном фрагменте, там где я перебираю Event-ы из channel, запустил этот аргумент в открываемый диалог так:
is RecyclerTransactionsViewModel.RecTransEvent.NavigateToDeleteTransactionScreen -> {
val action = RecyclerTransactionsFragmentDirections.actionGlobalDeleteTransactionDialogFragment(it.spend)
findNavController().navigate(action)
}
А DeleteTransactionViewModel ловлю этот аргумент Spend в SavedStateHandle:
class DeleteTransactionViewModel @Inject constructor(
private val repo: FinRepository,
@ApplicationScope private val applicationScope: CoroutineScope,
private val state: SavedStateHandle
) : ViewModel() {
val spend = state.get<Spend>("spend")
fun onConfirmClick(spend: Spend) = applicationScope.launch {
repo.deleteSpend(spend)
}
И в самом DeleteTransactionDalogFragment вызываю удаление так:
.setPositiveButton(requireContext().resources.getString(R.string.yes)) { _, _ ->
if (viewModel.spend != null) {
viewModel.onConfirmClick(viewModel.spend!!)
} else {
Timber.d("The Spend? id currently null")
}
}
Пока всё работает (и главное что при повороте экрана DialogFragment сохраняется, так как "живет" во ViewModel).