Почему RequireView () не возвращает представление onResume ()? - PullRequest
0 голосов
/ 14 марта 2020

Я анализирую данные с помощью Volley Request для метода onResume () моего фрагмента, чтобы заполнить макет проанализированными данными, которые мне нужны, чтобы получить представление о моем фрагменте, поэтому я вызываю requireView () onResume () после успешного разбора. Впервые мое приложение упало на одной строке, которую я собираюсь пометить * поговоркой:

java .lang.IllegalStateException: Fragment DataMain {1a53f20} (4f68cb4d-c05f- 4416-932e-26e455fbf106)} не вернул View из onCreateView (), или он был вызван ранее onCreateView ().

Это код:

class DataMain : Fragment(), CoroutineScope by MainScope() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_Data, container, false)
        DataBalance = view.findViewById(R.id.Data_balance)
        // Firebase User Auth
        getUID.requestUidToken()?.addOnSuccessListener { 

                    }?.addOnFailureListener {

                    val unregisteredView = inflater.inflate(R.layout.fragment_unregistred, container, false)
                    val registerNow = unregisteredView.findViewById<TextView>(R.id.textview_registernow)
                    registerNow.setOnClickListener {
                        val mIntent = Intent(activity, LoginMain::class.java)
                        requireActivity().startActivity(mIntent)
                    }
                }
            view
        } else {
            val unregisteredView = inflater.inflate(R.layout.fragment_unregistred, container, false)
            val registerNow = unregisteredView.findViewById<TextView>(R.id.textview_registernow)
            registerNow.setOnClickListener {
                val mIntent = Intent(activity, LoginMain::class.java)
                requireActivity().startActivity(mIntent)
            }
            unregisteredView
        }
    }

        private fun populateDataLayout(res: JSONObject, view: View) {
        val response = Gson().fromJson(res.toString(), ServerResponse::class.java)
        //here I need the view
        val lVDataMenu: ListView = view.findViewById(R.id.lV_DataMenu)
        lVDataMenu.adapter = lVadapter

        else if (response.code == 403) {

        }
}


    override fun onResume() {
        getUID.requestUidToken()?.addOnSuccessListener { getTokenResult ->
            Volley(config.DATA_LOADDATA, { res ->
                **CRASH**populateDataLayout(res,requireView())
            }, {
                tv_unverified.visibility = View.VISIBLE
            })
        }
        super.onResume()
    }

Я мог избавиться от использования "view.findViewById (R.id.lV_DataMenu)" в подпрограмме заполнения, но тогда я не пойму проблему здесь. Я не смог повторить ошибку, поэтому я и спрашиваю. Так почему же возможно, что requireView () не возвращает View? Это потому, что пользователь переключается на следующий фрагмент, в то время как Volley не заканчивает анализ? И как я могу это исправить?

1 Ответ

1 голос
/ 14 марта 2020
override fun onResume() {
    getUID.requestUidToken()?.addOnSuccessListener { getTokenResult ->
        Volley(config.DATA_LOADDATA, { res ->
            **CRASH**populateDataLayout(res,requireView())
        }, {
            tv_unverified.visibility = View.VISIBLE
        })
    }

Вы не звоните requireView() в onResume() здесь.

У вас есть два асинхронных вызова, и вы передаете им функции (эти лямбда-выражения в {}) в качестве параметров. Эти функции вызываются позже, например, когда завершается операция asyn c. В то время ваш фрагмент мог завершить свой жизненный цикл.

Две общие стратегии для его обработки:

  1. Отмена ожидающих асинхронных вызовов c, когда фрагмент завершается , Похоже, вы запускаете звонки в onCreateView() и onResume(). Аналогами жизненного цикла для них будут onDestroyView() и onPause(). Как это сделать, конкретно зависит от используемых вами асинхронных API-интерфейсов c.

  2. Запускайте и забывайте с проверкой целостности: после завершения асинхронного c проверьте, фрагмент еще жив, иначе ничего не делать. Например, замените

    populateDataLayout(res,requireView())
    

    на что-то вроде

    view?.let { populateataLayout(res, it) }
    

    , где view является равным нулю getView() аналогом ненулевого requireView().

...