我试图遵循官方谷歌文档https://developer.android.com/tools/data-binding/guide.html的数据绑定示例
除了我试图将数据投标应用到一个片段,而不是一个活动。
编译时我目前得到的错误是
错误:(37,27)没有指定资源类型(at 'text' with value '@{marsdata.martianSols})。
onCreate for fragment是这样的:
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MartianDataBinding binding = MartianDataBinding.inflate(getActivity().getLayoutInflater());
binding.setMarsdata(this);
}
onCreateView for fragment看起来像这样:
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.martian_data, container, false);
}
和部分我的布局文件片段看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="marsdata"
type="uk.co.darkruby.app.myapp.MarsDataProvider" />
</data>
...
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@{marsdata.martianSols}"
/>
</RelativeLayout>
</layout>
我的怀疑是MartianDataBinding不知道它应该与哪个布局文件绑定-因此出现错误。有什么建议吗?
你实际上被鼓励使用你生成的Binding的膨胀方法,而不是DataBindingUtil:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
MainFragmentBinding binding = MainFragmentBinding.inflate(inflater, container, false);
//set variables in Binding
return binding.getRoot();
}
(MainFragmentBinding为r.b ayout.main_fragment自动生成)
databindingutil . inflation()文档:
仅在layoutId预先未知的情况下使用此版本。否则,使用生成的Binding的膨胀方法来确保类型安全的膨胀。
每个人都在谈论膨胀(),但如果我们想在onViewCreated()中使用它呢?
可以使用具体绑定类的bind(视图)方法获取视图的ViewDataBinding实例。
通常我们这样写BaseFragment(简化):
// BaseFragment.kt
abstract fun layoutId(): Int
override fun onCreateView(inflater, container, savedInstanceState) =
inflater.inflate(layoutId(), container, false)
并在子片段中使用它。
// ConcreteFragment.kt
override fun layoutId() = R.layout.fragment_concrete
override fun onViewCreated(view, savedInstanceState) {
val binding = FragmentConcreteBinding.bind(view)
// or
val binding = DataBindingUtil.bind<FragmentConcreteBinding>(view)
}
如果所有fragment都使用数据绑定,您甚至可以使用类型参数使其更简单。
abstract class BaseFragment<B: ViewDataBinding> : Fragment() {
abstract fun onViewCreated(binding: B, savedInstanceState: Bundle?)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
onViewCreated(DataBindingUtil.bind<B>(view)!!, savedInstanceState)
}
}
我不知道是否可以在这里断言非空,但是。你懂的。如果你想让它为空,你可以这样做。
非常有用的关于数据绑定的博客:
https://link.medium.com/HQY2VizKO1
class FragmentBinding<out T : ViewDataBinding>(
@LayoutRes private val resId: Int
) : ReadOnlyProperty<Fragment, T> {
private var binding: T? = null
override operator fun getValue(
thisRef: Fragment,
property: KProperty<*>
): T = binding ?: createBinding(thisRef).also { binding = it }
private fun createBinding(
activity: Fragment
): T = DataBindingUtil.inflate(LayoutInflater.from(activity.context),resId,null,true)
}
在Fragment中像这样声明binding val:
private val binding by FragmentBinding<FragmentLoginBinding>(R.layout.fragment_login)
别忘了把这段话分段写下来
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return binding.root
}