Расширения Kotlin для Android и сохраненный фрагмент

Я использую в своем проекте расширения Kotlin для Android и столкнулся с поведением, которое не могу понять. Я использую этот код, чтобы сохранить свой фрагмент в действии:

val fragment = fragmentManager.findFragmentByTag("hello") ?: HelloFragment()
fragmentManager.beginTransaction()
               .replace(R.id.fragment_container, fragment, "hello")
               .commit()

Это сохраненный Fragment:

import kotlinx.android.synthetic.hello.*

public class HelloFragment : Fragment() {
    val text = "Hello world!"

    override fun onCreate(savedInstanceState: Bundle?) {
        super<Fragment>.onCreate(savedInstanceState)
        setRetainInstance(true)
    }

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater?.inflate(R.layout.hello, container, false)
    }

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

        text_view.setText(text) // <- does not work when retained
    }
}

и его XML-макет hello.xml:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/text_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center" />

Все работает так, как ожидалось — text_view.setText() отображает Hello world! на экране при первом запуске. Но при повороте экрана text_view.setText() не работает. Это странно, потому что text_view не может принимать значение NULL и должно ссылаться на какое-то представление. Если удалить setRetainInstance(true) и оставить фрагмент пересоздаваться каждый раз, то эта проблема исчезнет. Любые мысли, что может вызвать эту проблему?


person Lamorak    schedule 02.07.2015    source источник


Ответы (3)


UPD: проблема исправлена. Вам больше не нужно вызывать clearFindViewByIdCache() вручную.

Кэш View не очищается после вызова onDestroyView(). Существует открытая проблема.

На данный момент вы можете явно вызвать clearFindViewByIdCache() в onDestroyView() для очистки кеша. Этот метод является частью пакета synthetic, поэтому его необходимо импортировать.

import kotlinx.android.synthetic.*
person yanex    schedule 03.07.2015
comment
Теперь проблема исправлена. см. ответ @greenspand ниже - person activedecay; 25.01.2016

Просто для уточнения. Теперь проблема исправлена. Вам больше не нужно передавать clearFindViewByIdCache(). См. средство отслеживания проблем: https://youtrack.jetbrains.com/oauth?state=%2Fissue%2FKT-8073

person greenspand    schedule 15.10.2015

Я сам нашел ответ. Класс Fragment не расширяет макет напрямую — у него есть свойство view: View?, которое его хранит. Это должно быть довольно очевидно, так как он создан с помощью onCreateView. Чтобы получить доступ к свойствам в view, вы должны установить импорт

import kotlinx.android.synthetic.hello.view.*

а затем получить доступ к свойствам следующим образом

view?.text_view?.setText(text)

Обратите внимание, что эти свойства могут принимать значения NULL.

person Lamorak    schedule 02.07.2015
comment
Всегда ли нам нужно использовать clearFindViewByIdCache(), если мы используем import kotlinx.android.synthetic.* в наших фрагментах??? - person cesards; 12.04.2016
comment
Вам больше не нужно clearFindViewByIdCache() согласно другому ответу на этот вопрос. - person Lamorak; 12.04.2016