Kotlin Android 扩展和保留片段
Kotlin Android extensions and retained fragment
我在我的项目中使用 Kotlin Android extensions,我遇到了一些我无法理解的行为。我使用此代码将我的片段保留在 activity:
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
不可为空并且必须引用某些视图。如果您删除 setRetainInstance(true)
并在每次此问题消失时重新创建片段。有什么想法可能导致这个问题吗?
我自己找到了答案。 Fragment
class 不会直接膨胀布局 - 它有 属性 view: View?
来保存它。这应该很明显,因为它是用 onCreateView
创建的。为了访问 view
中的属性,您必须设置 import
import kotlinx.android.synthetic.hello.view.*
然后访问属性如下
view?.text_view?.setText(text)
请注意,这些属性可以为空。
UPD: 问题现已解决。您不必再手动调用 clearFindViewByIdCache()
。
View
调用 onDestroyView()
后未清除缓存。有一个open issue.
目前,您可以在 onDestroyView()
中显式调用 clearFindViewByIdCache()
来清除缓存。此方法是 synthetic
包的一部分,因此您必须导入它
import kotlinx.android.synthetic.*
澄清一下。该问题现已解决。您不必再通过 clearFindViewByIdCache()。请查看问题跟踪器:https://youtrack.jetbrains.com/oauth?state=%2Fissue%2FKT-8073
我在我的项目中使用 Kotlin Android extensions,我遇到了一些我无法理解的行为。我使用此代码将我的片段保留在 activity:
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
不可为空并且必须引用某些视图。如果您删除 setRetainInstance(true)
并在每次此问题消失时重新创建片段。有什么想法可能导致这个问题吗?
我自己找到了答案。 Fragment
class 不会直接膨胀布局 - 它有 属性 view: View?
来保存它。这应该很明显,因为它是用 onCreateView
创建的。为了访问 view
中的属性,您必须设置 import
import kotlinx.android.synthetic.hello.view.*
然后访问属性如下
view?.text_view?.setText(text)
请注意,这些属性可以为空。
UPD: 问题现已解决。您不必再手动调用 clearFindViewByIdCache()
。
View
调用 onDestroyView()
后未清除缓存。有一个open issue.
目前,您可以在 onDestroyView()
中显式调用 clearFindViewByIdCache()
来清除缓存。此方法是 synthetic
包的一部分,因此您必须导入它
import kotlinx.android.synthetic.*
澄清一下。该问题现已解决。您不必再通过 clearFindViewByIdCache()。请查看问题跟踪器:https://youtrack.jetbrains.com/oauth?state=%2Fissue%2FKT-8073