Android - правильно передавая обратный вызов в диалогAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Android - правильно передавая обратный вызов в диалог

Сообщение Anonymous »

Я хочу отобразить пользовательский диалог в моем приложении, в котором есть поле ввода.
Я расширил класс диалога и настройку макета, которую я хотел.
Проблема, которую я столкнулся, заключается в том, что мне нужен способ получить данные с ввода, если пользователь попадает в сохранение. < /p>
Первая попытка: Retrive via On Aattachment < /code> < /b /> hits> < /p>
. Интерфейс с одной функцией, которая возвращает это значение, сделал мой фрагмент (тот, который собирается вызвать пользовательский диалог). Их, я перевернул onattachfragment в моем пользовательском диалоге, как это:

Код: Выделить всё

class CustomDialogFragment private constructor() : DialogFragment() {

companion object {
fun getInstance(callback: Callback): CustomDialogFragment {
return Bundle().apply {
putSerializable("callback", callback)
}.let {
CustomDialogFragment().apply { arguments = it }
}
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
saveCallback = it.getSerializable("callback")!! as Callback
}
}

private lateinit var saveCallback: Callback

interface Callback : Serializable {
fun setText(text: String)
}

private var _binding: FragmentCustomDialogBinding? = null
private val binding get() = _binding!!

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentCustomDialogBinding.inflate(inflater, container, false)
return binding.root
}

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
return dialog
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupViews()
}

private fun setupViews() = binding.run {
closeIcon.setOnClickListener { closeDialog() }
cancelButton.setOnClickListener { closeDialog() }
saveButton.setOnClickListener { onSaveClicked() }
}

private fun onSaveClicked() = binding.run {
val strMaxPrice = maxPriceInput.text.toString()
saveCallback.setText(strMaxPrice)
closeDialog()
}

override fun onAttachFragment(childFragment: Fragment) {
super.onAttachFragment(childFragment)
saveCallback = childFragment as Callback
}

private fun closeDialog() {
requireDialog().hide()
}
}
< /code>
и на фрагменте, который отображает этот диалог: < /p>
class FirstFragment : Fragment(), Callback {

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.buttonFirst.setOnClickListener {
val fragmentManager = requireActivity().supportFragmentManager
val newFragment = CustomDialogFragment.getInstance(callback)
newFragment.show(fragmentManager, "dialog")
}
}

override fun setText(text: String) {
Toast.makeText(requireContext(), text, Toast.LENGTH_LONG).show()
}

...
}
Однако это не работает, потому что метод onattachfragment не называется.
Кроме того, этот метод устарел, так что ... давайте попробуем другой способ. Это значение в пакете диалога, поэтому, когда произойдут такие вещи, как изменения конфигурации, ваше значение не будет потеряно. Тем не менее, интерфейс не может быть сохранен на пакете, но сериализуемое значение может. Итак, давайте создадим интерфейс, который реализует этот метод: < /p>

Код: Выделить всё

companion object {
fun getInstance(callback: Callback): CustomDialogFragment {
return Bundle().apply {
putSerializable("callback", callback)
}.let {
CustomDialogFragment().apply { arguments = it }
}
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
saveCallback = it.getSerializable("callback")!! as Callback
}
}

private lateinit var saveCallback: Callback

interface Callback : Serializable {
fun setText(text: String)
}
< /code>
и на фрагменте, который будет показывать этот диалог: < /p>
class FirstFragment : Fragment(), CustomDialogFragment.Callback {

override fun setText(text: String) {
Toast.makeText(requireContext(), text, Toast.LENGTH_LONG).show()
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.buttonFirst.setOnClickListener {
val fragmentManager = requireActivity().supportFragmentManager
val newFragment = CustomDialogFragment.getInstance(this)
newFragment.show(fragmentManager, "dialog")
}
}
...
}

< /code>
Однако это звучало многообещающе и сработало (я мог бы вызвать диалог, отобразить его и получить значение), если я минимизирую свое приложение после отображения диалога (до или после закрытия диалога), мое приложение сбоя с BadparcelableException: < /p>
Fatal Exception: android.os.BadParcelableException
Parcelable encountered IOException writing serializable object (name = com.package.app.MyFragment)
< /code>
Итак, это тоже не сработало ... < /p>
 третья попытка: использование навигации и Safeargs < /h3>
Я помню, что у нас теперь есть навигация, так что давайте попробуем с этим: < /p>
graph: < /p>


my customfragment: < /p>
class CustomDialogFragment : DialogFragment() {

private val args: CustomDialogFragmentArgs by navArgs()
private val block = args.block
< /code>
Моя активность: < /p>
findNavController().navigate(MyFragmentDirections.toCustomDialogFragment(object : Callback {
override fun setText(text: String) {
Toast.makeText(requireContext(), text, Toast.LENGTH_LONG).show()
}
}))
< /code>
обратный вызов: < /p>
interface Callback : java.io.Serializable {
fun setText(text: Int)
}
< /code>
, который также не работал, отображая эту ошибку: < /p>
Caused by: java.lang.IllegalStateException: Fragment CustomDialogFragment{7fd896f} (a78e55c0-62f1-48c2-bc19-3f9d6f85adb2) has null arguments
Я знаю один из способов «решить проблему», который будет передавать обратный вызов как лямбда через конструктор CustomDialog, но я не уверен, что это хорошая практика.
>

Подробнее здесь: https://stackoverflow.com/questions/757 ... ogfragment
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»