使用DataBinding绑定ViewPager2内Fragment时EditText取值失败问题
问题原因及修复方案
1. EditText 配置为单向绑定,无法回写输入到ViewModel
你当前给EditText设置的android:text="@{signUp.txtEmail}"属于单向绑定,仅支持将ViewModel的数据同步到控件展示,不会把用户输入的内容反向同步到ViewModel的txtEmail属性,这是你拿不到输入值的核心原因。
要实现输入内容自动同步到ViewModel,改为双向绑定语法即可:
android:text="@={signUp.txtEmail}"
注意:ViewModel中的txtEmail必须是可观察类型,比如MutableLiveData<String>或实现了Observable接口的自定义字段,否则双向绑定无法生效
2. 未给DataBinding绑定LifecycleOwner
DataBinding需要绑定生命周期所有者才能正常感知数据变化、完成双向同步逻辑,你当前的代码中没有做这一步配置,也会导致绑定异常。
修改Fragment的onCreateView代码,补充LifecycleOwner绑定:
override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { // 注意第三个参数改为false,ViewPager2会自动处理子Fragment的View挂载,传true会导致布局重复加载 mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_sign_up_main,container,false) mBinding?.signUp = vm // 新增生命周期绑定 mBinding?.lifecycleOwner = viewLifecycleOwner return mBinding?.root!! }
3. 共享ViewModel的传递方式有隐患
你当前直接通过构造函数把父Fragment的ViewModel传给子Fragment,这种方式在Fragment重建(比如屏幕旋转、ViewPager2切页销毁重建子Fragment)时会出现实例丢失、内存泄漏问题。
更规范的共享父Fragment ViewModel的方式是直接在子Fragment中获取,不需要通过构造传参:
class SignUpMainFragment:Fragment() { private var mBinding:FragmentSignUpMainBinding?=null // 直接获取父Fragment作用域的ViewModel,自动和父Fragment共享同一份实例 private val vm: SignUpFragmentVM by viewModels(ownerProducer = { requireParentFragment() }) override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_sign_up_main,container,false) mBinding?.signUp = vm mBinding?.lifecycleOwner = viewLifecycleOwner return mBinding?.root!! } override fun onDestroyView() { super.onDestroyView() // 清空绑定引用,避免内存泄漏 mBinding = null } }
完成以上修改后,EditText的输入值即可正常同步到ViewModel中。
内容的提问来源于stack exchange,提问作者GaleLiu
相关产品推荐
相关产品推荐

