I am using Kotlin Android extensions in my project and I came across some behavior that I am unable to understand. I use this code to retain my fragment in the activity:
val fragment = fragmentManager.findFragmentByTag("hello") ?: HelloFragment()
fragmentManager.beginTransaction()
.replace(R.id.fragment_container, fragment, "hello")
.commit()
This is the retained 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
}
}
and its XML layout 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" />
Everything works as expected – the text_view.setText()
displays Hello world! on screen on the first launch. But when you rotate the screen the text_view.setText()
does not work. This is weird because text_view
is not nullable and has to reffer to some view. If you remove setRetainInstance(true)
and leave the fragment recreate every time this problem disappears. Any thoughts what might cause this problem?
I have found the answer myself. The Fragment
class does not inflate the layout directly – it has property view: View?
which holds it. This should be pretty obvious since it is created with onCreateView
. In order to access the properties within the view
you have to set the import
import kotlinx.android.synthetic.hello.view.*
and then access the properties as follows
view?.text_view?.setText(text)
Note that these properties are nullable.
UPD: The issue is fixed now. You don't have to call clearFindViewByIdCache()
manually anymore.
View
cache is not cleared after calling onDestroyView()
. There is an open issue.
For now, you can explicitly invoke clearFindViewByIdCache()
in onDestroyView()
to clear the cache. This method is part of the synthetic
package so you have to import it
import kotlinx.android.synthetic.*
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With