DylanCaiCoding/ViewBindingKTX

Fragment绑定失败?

aheven opened this issue · 2 comments

版本号:2.0.5

Fragment绑定失败?原始代码为:

<!-- activity_main.xml -->
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="**.main.MainFragment"
    android:fitsSystemWindows="true"/>

<!-- MainFragment -->
class MainFragment : Fragment() {
    private val binding:FragmentMainBinding by binding()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.content.text = "123456"
    }
}

但是在页面中,MainFragment的布局无法加载出来。

查看源码,发现并没有将View绑定至Fragment的相关代码:

class FragmentBindingProperty<VB : ViewBinding>(private val clazz: Class<VB>) : ReadOnlyProperty<Fragment, VB> {

  override fun getValue(thisRef: Fragment, property: KProperty<*>): VB =
    requireNotNull(thisRef.view) { "The property of ${property.name} has been destroyed." }
      .getBinding(clazz).also { binding ->
        if (binding is ViewDataBinding) binding.lifecycleOwner = thisRef.viewLifecycleOwner
      }
}

是否和这个有关系?

看到示例,Fragment 构造传递了资源 ID,所以是通过这种方式初始化的。因此 by binding() 的作用仅为绑定 Fragment 视图。
对于 Androidx 低版本,例如,AppCompatDialogFragmentandroidx.appcompat 1.4.0 之前未添加 ResourceId 构造参数,AppCompatActivityandroidx.appcompat 1.1.0 之前未添加 ResourceId 构造参数。

建议添加 View 为空的时候抛出异常提示将 View 添加到 Fragment。

感谢反馈,已将异常提示改为 The constructor missing layout id or the property of ${property.name} has been destroyed.

DialogFragment 是推荐下面这么来用,binding 写在 Dialog 里。

class LoadingDialogFragment(private val text: String? = null) : DialogFragment() {

  override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    isCancelable = false
    return LoadingDialog(requireContext())
  }

  inner class LoadingDialog(context: Context) : Dialog(context, R.style.DialogTheme) {
    private val binding: DialogLoadingBinding by binding()

    override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      window?.setLayout(MATCH_PARENT, WRAP_CONTENT)
      binding.tvMessage.text = "Wait a minute..."
    }
  }
}