我试图关注来自官方google doc https://developer.android.com/tools/data-binding/guide.html的数据绑定示例
除了我试图将数据绑定应用于片段而不是活动。
我在编译时遇到的错误
Error:(37, 27) No resource type specified (at 'text' with value '@{marsdata.martianSols}.
onCreate
如下所示:
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MartianDataBinding binding = MartianDataBinding.inflate(getActivity().getLayoutInflater());
binding.setMarsdata(this);
}
片段的 onCreateView
如下所示:
@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
不知道它应该绑定哪个布局文件 - 因此错误。有什么建议吗?
答案 0 :(得分:274)
数据绑定实现必须在片段的onCreateView
方法中,删除OnCreate
方法中存在的任何数据绑定,
您的onCreateView
应如下所示:
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
MartianDataBinding binding = DataBindingUtil.inflate(
inflater, R.layout.martian_data, container, false);
View view = binding.getRoot();
//here data must be an instance of the class MarsDataProvider
binding.setMarsdata(data);
return view;
}
答案 1 :(得分:43)
实际上,我们鼓励您使用生成的Binding的inflate
方法而不是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();
}
Docs for DataBindingUtil.inflate():
仅在事先未知layoutId时才使用此版本。否则,使用生成的Binding的膨胀方法来确保类型安全的通货膨胀。
答案 2 :(得分:7)
可以简单地检索视图对象,如下所述
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = DataBindingUtil.inflate(inflater, R.layout.layout_file, container, false).getRoot();
return view;
}
答案 3 :(得分:7)
在Android DataBinding中尝试此操作
FragmentMainBinding binding;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_main, container, false);
View rootView = binding.getRoot();
initInstances(savedInstanceState);
return rootView;
}
答案 4 :(得分:6)
其他答案也可能效果很好,但是我想告诉您最佳方法。
Binding class's inflate
。一种选择是用DataBindingUtil
进行充气,但只有在您不知道已生成绑定类的情况下才这样做。
-您已自动生成binding class
,请使用该类,而不要使用DataBindingUtil
。
在Java中
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
HomeFragmentBinding binding = HomeFragmentBinding.inflate(inflater, container, false);
//set binding variables here
return binding.getRoot();
}
在科特林
lateinit var binding: HomeFragmentBinding
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = HomeFragmentBinding.inflate(inflater, container, false)
return binding.root
}
在 DataBindingUtil 类 documentation 中,您可以看到。
充气
T inflate (LayoutInflater inflater, int layoutId, ViewGroup parent, boolean attachToParent)
仅在预先未知layoutId时使用此版本。否则,请使用生成的Binding的inflate方法来确保类型安全 通货膨胀。
如果未生成布局分类类,请参见 this answer 。
答案 5 :(得分:5)
在我的代码中工作。
private FragmentSampleBinding dataBiding;
private SampleListAdapter mAdapter;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
dataBiding = DataBindingUtil.inflate(inflater, R.layout.fragment_sample, null, false);
return mView = dataBiding.getRoot();
}
答案 6 :(得分:4)
数据绑定片段的完整示例
FragmentMyProgramsBinding是为res / layout / fragment_my_programs生成的绑定类
public class MyPrograms extends Fragment {
FragmentMyProgramsBinding fragmentMyProgramsBinding;
public MyPrograms() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
FragmentMyProgramsBinding fragmentMyProgramsBinding = DataBindingUtil.inflate(inflater, R
.layout.fragment_my_programs, container, false);
return fragmentMyProgramsBinding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
}
答案 7 :(得分:4)
如果您使用的是 ViewModel 和 LiveData ,这是足够的语法
科林语法:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return MartianDataBinding.inflate(
inflater,
container,
false
).apply {
setLifecycleOwner(this@MartianData)
vm = viewModel // Attach your view model here
}.root
}
答案 8 :(得分:3)
Kotlin语法:
lateinit var binding: MartianDataBinding
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.martian_data, container, false)
return binding.root
}
答案 9 :(得分:1)
就像大多数人所说的那样,但不要忘记设置 LifeCycleOwner
Java示例
即
with StringIO(txt) as file:
for line in file:
row = line.strip().split(",")
for word in row:
if word not in dct:
dct[word] = len(dct)
答案 10 :(得分:0)
Kotlin的另一个例子:
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val binding = DataBindingUtil
.inflate< MartianDataBinding >(
inflater,
R.layout.bla,
container,
false
)
binding.modelName = // ..
return binding.root
}
请注意,名称“MartianDataBinding”取决于布局文件的名称。如果文件名为“martian_data”,那么正确的名称将是MartianDataBinding。
答案 11 :(得分:0)
每个人都谈论inflate()
,但是如果我们想在onViewCreated()
中使用它呢?
您可以使用具体绑定类的 bind(view)
方法来获取ViewDataBinding
的{{1}}实例。
通常,我们将BaseFragment写成这样(简化):
view
并在子片段中使用它。
// BaseFragment.kt
abstract fun layoutId(): Int
override fun onCreateView(inflater, container, savedInstanceState) =
inflater.inflate(layoutId(), container, false)
如果所有Fragments都使用数据绑定,则甚至可以使用type参数使其更简单。
// 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)
}
我不知道在那里声明非null是可以的,但是..你明白了。如果希望它可以为空,则可以这样做。
答案 12 :(得分:0)
关于数据绑定的非常有用的博客: 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中这样声明绑定val:
private val binding by FragmentBinding<FragmentLoginBinding>(R.layout.fragment_login)
别忘了将其写在片段中
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return binding.root
}
答案 13 :(得分:0)
我一直在为我的应用程序找到答案,这是Kotlin语言的答案。
private lateinit var binding: FragmentForgetPasswordBinding override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { binding=DataBindingUtil.inflate(inflater,R.layout.fragment_forget_password,container,false) val viewModel=ViewModelProvider(this).get(ForgetPasswordViewModel::class.java) binding.recoveryViewModel=viewModel viewModel.forgetPasswordInterface=this return binding.root }