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-макет Здравствуйте.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 не является нулевым и должен относиться к некоторому представлению. Если вы удаляете setRetainInstance(true) и оставляете фрагмент воссоздавать каждый раз, когда эта проблема исчезает. Есть мысли, что может вызвать эту проблему?

3 9

3 ответа:

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

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

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

import kotlinx.android.synthetic.*

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

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

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

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

view?.text_view?.setText(text)
Обратите внимание, что эти свойства могут быть обнулены.