绑定不适用于与 ViewStub 关联的片段
Binding is not applying to a fragments associated with ViewStub
我遇到了当前的问题。现在我正在尝试懒惰地膨胀一堆片段以获得更好的性能,它们是 ViewPager 的一部分。我找到的唯一解决方案是使用 ViewStub。
这是我到目前为止所做的:
abstract class ViewStubFragment: BaseFragment() {
private lateinit var binding: FragmentViewStubBinding
private var mSavedInstanceState: Bundle? = null
private var hasInflated = false
private var viewStub: ViewStub? = null
private var visible = false
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentViewStubBinding.inflate(inflater, container, false)
viewStub = binding.fragmentViewStub.viewStub
viewStub?.layoutResource = getViewStubLayoutResource()
mSavedInstanceState = savedInstanceState
if(visible && !hasInflated) {
val inflatedView = viewStub?.inflate()
if (inflatedView != null) {
onCreateViewAfterViewStubInflated(inflatedView, mSavedInstanceState)
}
}
return binding.root
}
protected abstract fun onCreateViewAfterViewStubInflated(
inflatedView: View,
savedInstanceState: Bundle?
)
@LayoutRes
protected abstract fun getViewStubLayoutResource(): Int
@CallSuper
protected fun afterViewStubInflated(originalViewContainerWithViewStub: View?) {
hasInflated = true
if (originalViewContainerWithViewStub != null) {
val progressBar = binding.progressBar
progressBar.visibility = View.GONE
}
}
override fun onResume() {
super.onResume()
visible = true
if (viewStub != null && !hasInflated) {
val inflatedView = viewStub!!.inflate()
onCreateViewAfterViewStubInflated(inflatedView, mSavedInstanceState)
afterViewStubInflated(view)
}
}
对应布局:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/progress_bar"
android:foregroundGravity="center"
android:layout_gravity="center"
android:indeterminate="true"
android:layout_width="48dp"
android:layout_height="48dp"/>
<ViewStub
android:id="@+id/fragment_view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
</layout>
我正在尝试延迟膨胀的 HomeFragment 的部分代码:
class HomeFragment : ViewStubFragment() {
lateinit var binding: FragmentHomeBinding
........
override fun onCreateViewAfterViewStubInflated(
inflatedView: View,
savedInstanceState: Bundle?
) {
setDataBinding()
observeLiveData()
}
override fun getViewStubLayoutResource(): Int {
binding = FragmentHomeBinding.inflate(layoutInflater)
return binding.root.sourceLayoutResId
}
问题是当 setDataBinding()
被调用时,由于某种原因没有应用绑定,因此像 RecyclerView 这样的视图没有显示在屏幕上或者点击事件不工作。我已经搜索了几个小时,但找不到与此问题相关的解决方案。
经过一个小时的努力,我找到了一个解决方案,不确定它是否是最好的。
if(visible && !hasInflated) {
inflatedViewBinding = binding.fragmentViewStub.binding
val inflatedView = viewStub?.inflate()
if (inflatedView != null) {
onCreateViewAfterViewStubInflated(inflatedView, mSavedInstanceState, inflatedViewBinding)
}
}
我将存储在 ViewStubProxy
中的绑定(与膨胀布局关联)作为 onCreateViewAfterViewStubInflated()
中的参数传递,然后将 HomeFragment 绑定分配给它。
override fun onCreateViewAfterViewStubInflated(
inflatedView: View,
savedInstanceState: Bundle?,
binding: ViewDataBinding?
) {
this.binding = binding as FragmentHomeBinding
.......
}
我遇到了当前的问题。现在我正在尝试懒惰地膨胀一堆片段以获得更好的性能,它们是 ViewPager 的一部分。我找到的唯一解决方案是使用 ViewStub。 这是我到目前为止所做的:
abstract class ViewStubFragment: BaseFragment() {
private lateinit var binding: FragmentViewStubBinding
private var mSavedInstanceState: Bundle? = null
private var hasInflated = false
private var viewStub: ViewStub? = null
private var visible = false
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentViewStubBinding.inflate(inflater, container, false)
viewStub = binding.fragmentViewStub.viewStub
viewStub?.layoutResource = getViewStubLayoutResource()
mSavedInstanceState = savedInstanceState
if(visible && !hasInflated) {
val inflatedView = viewStub?.inflate()
if (inflatedView != null) {
onCreateViewAfterViewStubInflated(inflatedView, mSavedInstanceState)
}
}
return binding.root
}
protected abstract fun onCreateViewAfterViewStubInflated(
inflatedView: View,
savedInstanceState: Bundle?
)
@LayoutRes
protected abstract fun getViewStubLayoutResource(): Int
@CallSuper
protected fun afterViewStubInflated(originalViewContainerWithViewStub: View?) {
hasInflated = true
if (originalViewContainerWithViewStub != null) {
val progressBar = binding.progressBar
progressBar.visibility = View.GONE
}
}
override fun onResume() {
super.onResume()
visible = true
if (viewStub != null && !hasInflated) {
val inflatedView = viewStub!!.inflate()
onCreateViewAfterViewStubInflated(inflatedView, mSavedInstanceState)
afterViewStubInflated(view)
}
}
对应布局:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/progress_bar"
android:foregroundGravity="center"
android:layout_gravity="center"
android:indeterminate="true"
android:layout_width="48dp"
android:layout_height="48dp"/>
<ViewStub
android:id="@+id/fragment_view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
</layout>
我正在尝试延迟膨胀的 HomeFragment 的部分代码:
class HomeFragment : ViewStubFragment() {
lateinit var binding: FragmentHomeBinding
........
override fun onCreateViewAfterViewStubInflated(
inflatedView: View,
savedInstanceState: Bundle?
) {
setDataBinding()
observeLiveData()
}
override fun getViewStubLayoutResource(): Int {
binding = FragmentHomeBinding.inflate(layoutInflater)
return binding.root.sourceLayoutResId
}
问题是当 setDataBinding()
被调用时,由于某种原因没有应用绑定,因此像 RecyclerView 这样的视图没有显示在屏幕上或者点击事件不工作。我已经搜索了几个小时,但找不到与此问题相关的解决方案。
经过一个小时的努力,我找到了一个解决方案,不确定它是否是最好的。
if(visible && !hasInflated) {
inflatedViewBinding = binding.fragmentViewStub.binding
val inflatedView = viewStub?.inflate()
if (inflatedView != null) {
onCreateViewAfterViewStubInflated(inflatedView, mSavedInstanceState, inflatedViewBinding)
}
}
我将存储在 ViewStubProxy
中的绑定(与膨胀布局关联)作为 onCreateViewAfterViewStubInflated()
中的参数传递,然后将 HomeFragment 绑定分配给它。
override fun onCreateViewAfterViewStubInflated(
inflatedView: View,
savedInstanceState: Bundle?,
binding: ViewDataBinding?
) {
this.binding = binding as FragmentHomeBinding
.......
}