Android Kotlin: функция переопределения интерфейса не вызывается - PullRequest
0 голосов
/ 09 июля 2020

У меня есть FragmentA и FragmentB. Я пытаюсь обновить значения FragmentA из FragmentB

У меня есть интерфейс:

interface FragmentCallback {
    fun onDataSent(sendUpdatedData: String, position: Int?)
}

В FragmentA я переопределяю функцию интерфейса. Я также создаю экземпляр FragmentB и вызываю функцию setFragmentCallback

class FragmentA: Fragment(), FragmentCallback {

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        FragmentB().setFragmentCallback(this)
    }

    //This function is not being called from FragmentB...
    override fun onDataSent(sendUpdatedData: String, position: Int?) {
            updateRecyclerView(sendUpdatedData, position!!)
    }

В FragmentB (который находится поверх FragmentA) я создаю экземпляр интерфейса FragmentCallback. Когда я закончу редактирование и вставлю фрагмент (backstack), я вызываю переопределенную функцию из FragmentA (onDataSent).

class FragmentB: Fragment(){
    private var fragmentCallback: FragmentCallback? = null

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
    
        btn_save.setOnClickListener{
            fragmentCallback?.onDataSent(et_new_text.text.toString(), position )
            fragmentManager?.popBackStack()
        }
    }

    fun setFragmentCallback(callback: FragmentCallback?) {
        fragmentCallback = callback
    }
}

По какой-то причине, когда я открываю FragmentB и вызываю onDataSent через строку :

fragmentCallback?.onDataSent(et_new_text.text.toString(), position)

onDataSent на самом деле НЕ будет вызываться.

Ответы [ 2 ]

2 голосов
/ 09 июля 2020

Используйте FragmentResultListener в FragmentA:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setFragmentResultListener("requestKey") { key, bundle ->
        val sendUpdatedData = bundle.getString("sendUpdatedData")
        // Do something with the result...
    }
}

Затем в FragmentB установите результат:

btn_save.setOnClickListener{
    val result = et_new_text.text.toString()
    setFragmentResult("requestKey", bundleOf("sendUpdatedData" to result))
    ...
}

Посмотрите официальную документацию .

Старомодный способ использует Activity для связи между двумя фрагментами. Вы также можете использовать общую ViewModel для обмена данными.

0 голосов
/ 09 июля 2020

Вы тоже можете попробовать это.

Пусть ваша активность реализует ваш интерфейс.

class YourActivity : FragmentCallback{
    override fun onDataSent(sendUpdatedData: String, position: Int?) {
       // Get Fragment A
       val fraga: FragmentA? = 
              supportFragmentManager.findFragmentById(R.id.fragment_a) as FragmentA?
            fraga.updateRecyclerView(sendUpdatedData,position)
          }
}

В вашем фрагментеB отправьте данные следующим образом.

class FragmentB : Fragment() {
    var mCallback: FragmentCallback? = null

    override fun onAttach(activity: Activity) {
        super.onAttach(activity)

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        mCallback = try {
            activity as FragmentCallback
        } catch (e: ClassCastException) {
            throw ClassCastException(
                activity.toString()
                        + " must implement TextClicked"
            )
        }
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        mCallback.onDataSent(et_new_text.text.toString(), position)
        fragmentManager?.popBackStack()
    }
    
    override fun onDetach() {
        mCallback = null // => avoid leaking, thanks @Deepscorn
        super.onDetach()
    }
}

В вашем FragmentA.

class FragmentA : Fragment() {
    fun updateRecyclerView(sendUpdatedData: String, position: Int?) {
        // Here you'll have it
    }
}
...