Хорошо, у меня есть фрагмент, который отображает информацию об учетной записи пользователя.
Способ, которым это работает, - это отправка запроса, который может или не может коснуться сервера, в зависимости от того, какая информация уже кэширована.
Когда информация доступна, выполняется обратный вызов, при котором фрагмент обновляет свои текстовые поля.
Однако в этот момент пользовательский интерфейс необходимо обновить, поэтому я хотел бы выпустить какой-то видinvalidate
...
За исключением того, что это совершенно ничего не делает.
Сначала я заметил, что this.view
возвращает null
.Поэтому вместо того, чтобы полагаться на это, я сохраняю представление, которое создаю в явном виде в onCreateView
.
Затем после обновления текстовых полей я вызываю fragmentView.postInvalidate()
..., который ничего не делает.
Я также попытался doAsync { uiThread { fragmentView.invalidate() } }
..., который также ничего не делает.
Затем я нашел этот ответ и попытался
val fragment = this
doAsync { uiThread {
activity!!.supportFragmentManager.beginTransaction().detach(fragment).commit()
activity!!.supportFragmentManager.beginTransaction().attach(fragment).commit()
}}
... что даже хуже, чемничего не делать, потому что два других способа, по крайней мере, обновят представление, если вы переключитесь на другой фрагмент и обратно, тогда как это навсегда откажется отображать любую полезную информацию.
Так что, возможно, я могу "обмануть",задержка вызова до super::setUserVisibleHint
до тех пор, пока я не обновлю значения ... нет, я не могу.
Что я могу сделать, хотя яможет вызвать перерисовку пользовательского интерфейса, поджаривая что-то.Вот чем я сейчас занимаюсь.Но тем не менее, это не может быть решением.
Как мне получить правильное обновление пользовательского интерфейса?
О, а это android.support.v4.app.Fragment
, и я использую android.support.v4.app.FragmentStatePagerAdapter
для переключения между фрагментами, если это имеет значение.
Полный код фрагмента:
class AccountFragment : Fragment() {
lateinit var fragmentView: View
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
val view = inflater.inflate(R.layout.fragment_account, container, false)
/*for some reason [this.view] remains null when we later try to use it, so we're explicitly storing a reference*/
fragmentView = view
return view
}
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
if(isVisibleToUser)setAccountInformation()
super.setUserVisibleHint(isVisibleToUser)
}
private fun setAccountInformation(){
val um = DataConfig.getUserManager()
val au = um.getActiveUser()
um.getUserInfo(au, Callback(
onResponse = {when(it){
is SuccessfulAccountGetResponse -> {
val info = it.result
usernameText.text = info.name
uuidText.text = info.uuid
adminText.text = if(info.isAdmin) "YES" else "NO"
createdText.text = info.created.toString()
lastLoginText.text = info.lastLogin?.toString() ?: "-"
//now actually force the new information to show up
refreshUI()
}
else -> doAsync { uiThread{ activity?.longToast("could not get information") } }
}},
onError = {doAsync { uiThread { activity?.longToast("error: $it") } }}
))
}
/** forces a refresh, making changes visible*/
private fun refreshUI(){
/*hack: force a redraw by toasting */
doAsync { uiThread { activity?.toast("updating values") } }
//THIS does absolutely nothing: //TODO: figure out why
// fragmentView.postInvalidate()
}
}