Как подключить прослушиватель с компонентами навигации в пределах 2 фрагментов

#android #kotlin #android-fragments #android-architecture-navigation

Вопрос:

Я перехожу от фрагмента A к фрагменту B , во Фрагменте B мне нужно вызвать обратный вызов , созданный во фрагменте A, я не хочу использовать для этого общую модель представления, вместо этого я просто хочу подключить своего слушателя из фрагмента A

В настоящее время это мой подход

   class FragmentA: MyListener {
    
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            
             FragmentB().apply {
                this.myListener = this@FragmentA
            }
          myButton.setOnClickListener { findNavController().navigate(R.id.fragmentB) }
        }

 override fun launchFunction() { ... }
 

Теперь из моего фрагмента B я хочу запустить этот прослушиватель в другом методе, который у меня есть, но интерфейс имеет значение null

 class FragmentB {

 val myListener: MyListener? = null

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

         myListener.launchFunction()
    }
 

Но это не работает, я подозреваю, что из FragmentA я правильно применяю прослушиватель к экземпляру FragmentB, который отличается от того, который использует NavController для навигации

Как я могу подойти к этому ?

Спасибо

Комментарии:

1. Небезопасно вызывать любого слушателя для фрагмента в заднем стеке. Есть ли причина, по которой вы не используете API для возврата результата ?

2. Я не возвращаю результат, но вместо этого мне нужно запустить операцию из фрагмента A @ianhanniballake

3. Я думаю, что я пойду с этим developer.android.com/guide/navigation/… и просто вставьте фрагмент b, чтобы выполнить метод фрагмента A @ianhanniballake

Ответ №1:

Попробуйте использовать следующий код, он будет работать.

 //Receiver class
class CustomResultReceiver(handler: Handler?, receiver: 
ResultReceiverCallBack) :
ResultReceiver(handler), Serializable {
private var mReceiver: ResultReceiverCallBack = receiver

override fun onReceiveResult(resultCode: Int, resultData: Bundle) {
    mReceiver?.onLaunch(true, resultCode, resultData)
}

interface ResultReceiverCallBack {
    fun onLaunch(action: Boolean, resultCode: Int, resultData: Bundle)
}

}



//Fragment A
Class FragmentA:Fragment(),CustomResultReceiver.ResultReceiverCallBack {
private lateinit var binding: FragmentABinding

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

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

binding.dialogButton.setOnClickListener{
findNavController().navigate(
    R.id.action_FragmentA_to_FragmentB,
    Bundle().apply { putSerializable("key", 
 CustomResultReceiver(Handler(requireContext().mainLooper), 
  this@FragmentA))})
}
}

override fun onLaunch(action: Boolean, resultCode: Int, resultData: 
Bundle) {
toast(“Fragment B launch“)
}

} 



//Fragment B 
Class FragmentB:Fragment(){
private lateinit var binding: FragmentBBinding
private var resultReceiver: ResultReceiver? = null

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

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
 arguments.let {
 resultReceiver = arguments?.getSerializable("key") as 
 CustomResultReceiver
}
resultReceiver?.send(1,Bundle())
}
}