找不到我绑定的 inflate 方法(使用 Android,数据绑定。)
The inflate method for my binding is not found (using Android, Data Binding.)
我正在使用数据绑定来绑定我的 Android 应用中的布局。
我已经设置了布局 (my_custom.xml) 并且生成了绑定 class (MyCustomBinding),但是 Android Studio 似乎没有找到 .inflate(.. .) Binding class 方法,立即将其标记为错误(红色文本!)。
虽然代码似乎是正确的,因为它可以很好地编译和构建到 APK 中。
如何使 Android Studio 正确更新?
代码示例:
这是我的自定义查看代码:
public class MyCustomView extends FrameLayout {
public MyCustomView(Context context) {
this(context, null, 0);
}
public MyCustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
MyCustomBinding binding = MyCustomBinding.inflate(inflater, this, true);
binding.aButton.setText("Whatever");
}
}
布局定义为:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/a_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me!"
android:padding="10dp"
android:background="#000"
android:textColor="#fff"
android:layout_gravity="center"
/>
</FrameLayout>
</layout>
这是问题所在:(突出显示为红色)
您可以尝试为您的绑定布局设置自定义 class 名称,并在您的自定义视图中引用它以明确您使用的布局:
<layout>
<data class="MyCustomBinding">
</data>
</layout>
如果这不起作用,请使用 DataBindingUtil
而不是 MyCustomBinding
,它 returns 基础 DataBinding class 并且有一个 inflate()
方法:
MyCustomBinding binding = DataBindingUtil.inflate(inflater, this, true);
来自docs:
Sometimes the binding cannot be known in advance. In such cases, the binding can be created using the DataBindingUtil class:
ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId,
parent, attachToParent);
ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);
AndroidStudio 中有些事情没有完成,因为您还没有真正实现数据绑定。
将变量添加到布局的 data
元素后,将按预期找到 inflate
方法。也就是说,您实际上并没有通过直接通过绑定设置文本字段的值来获得数据绑定的好处。您应该改为在绑定中设置视图模型,然后让绑定相应地更新视图。例如:
创建视图模型:
public class MyViewModel {
public final ObservableField<String> name;
public MyViewModel(String name) {
this.name = new ObservableField<>(name);
}
}
并在您的布局中使用它
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="model" type="com.victoriaschocolates.conceirge.MyViewModel" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{model.name}"
android:padding="10dp"
android:background="#000"
android:textColor="#fff"
android:layout_gravity="center"
/>
</FrameLayout>
</layout>
(注意 data
元素中声明的 variable
,以及它在 TextView 的 text
属性中的引用方式)
然后在您的自定义视图中绑定两者:
public class MyCustomView extends FrameLayout {
public MyCustomView(Context context) {
this(context, null, 0);
}
public MyCustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
MyCustomBinding binding = MyCustomBinding.inflate(inflater, this, true);
MyViewModel model = new MyViewModel("Whatever");
binding.setModel(model);
}
}
当然,在自定义视图 class 中通过 setter 传递数据可能会更好,甚至从容器视图传递(参见 http://developer.android.com/tools/data-binding/guide.html#includes)
你不需要那种类型的东西,数据绑定包括数据绑定实用程序class我们开始吧。
public MyCustomView(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
MyCustomBinding binding = DataBindingUtil.inflate(inflater, this, true);
binding.aButton.setText("Whatever");
}
这是基于最新数据绑定和 androidx 的更新答案,我来这里解决这个问题是为了解决我自己的问题,在看了上面的答案之后,我通过自己的工作代码片段开发。希望这有帮助
public class CustomActionBar1 extends RelativeLayout {
public MutableLiveData<String> title = new MutableLiveData<>("Sample text");
CustomActionBar1Binding binding;
public CustomActionBar1(Context context) {
super(context);
init(context, this);
}
public CustomActionBar1(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, this);
}
public CustomActionBar1(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, this);
}
public CustomActionBar1(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, this);
}
private void init(Context context, ViewGroup viewGroup) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
binding = DataBindingUtil.inflate(inflater, R.layout.custom_action_bar_1, viewGroup, true);
}
// helper to change title
public void changeTitle(String title) {
if (title != null)
this.title.setValue(title);
}
public void setTitleVisibility(Boolean visibile){
binding.titleText.setVisibility(visibile ? View.VISIBLE : View.INVISIBLE);
}
}
Xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="customActionBar1"
type="com.actionBar.CustomActionBar1" />
</data>
<RelativeLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:background="@color/yellow"
android:layout_height="@dimen/action_bar_height"
android:id="@+id/main_header_relative">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@{customActionBar1.title}"
android:layout_centerInParent="true"
android:gravity="center"
android:id="@+id/titleText"
android:visibility="visible"
android:textColor="@color/black" />
</RelativeLayout>
</layout>
我正在使用数据绑定来绑定我的 Android 应用中的布局。
我已经设置了布局 (my_custom.xml) 并且生成了绑定 class (MyCustomBinding),但是 Android Studio 似乎没有找到 .inflate(.. .) Binding class 方法,立即将其标记为错误(红色文本!)。
虽然代码似乎是正确的,因为它可以很好地编译和构建到 APK 中。
如何使 Android Studio 正确更新?
代码示例:
这是我的自定义查看代码:
public class MyCustomView extends FrameLayout {
public MyCustomView(Context context) {
this(context, null, 0);
}
public MyCustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
MyCustomBinding binding = MyCustomBinding.inflate(inflater, this, true);
binding.aButton.setText("Whatever");
}
}
布局定义为:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/a_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me!"
android:padding="10dp"
android:background="#000"
android:textColor="#fff"
android:layout_gravity="center"
/>
</FrameLayout>
</layout>
这是问题所在:(突出显示为红色)
您可以尝试为您的绑定布局设置自定义 class 名称,并在您的自定义视图中引用它以明确您使用的布局:
<layout>
<data class="MyCustomBinding">
</data>
</layout>
如果这不起作用,请使用 DataBindingUtil
而不是 MyCustomBinding
,它 returns 基础 DataBinding class 并且有一个 inflate()
方法:
MyCustomBinding binding = DataBindingUtil.inflate(inflater, this, true);
来自docs:
Sometimes the binding cannot be known in advance. In such cases, the binding can be created using the DataBindingUtil class:
ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId,
parent, attachToParent);
ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);
AndroidStudio 中有些事情没有完成,因为您还没有真正实现数据绑定。
将变量添加到布局的 data
元素后,将按预期找到 inflate
方法。也就是说,您实际上并没有通过直接通过绑定设置文本字段的值来获得数据绑定的好处。您应该改为在绑定中设置视图模型,然后让绑定相应地更新视图。例如:
创建视图模型:
public class MyViewModel {
public final ObservableField<String> name;
public MyViewModel(String name) {
this.name = new ObservableField<>(name);
}
}
并在您的布局中使用它
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="model" type="com.victoriaschocolates.conceirge.MyViewModel" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{model.name}"
android:padding="10dp"
android:background="#000"
android:textColor="#fff"
android:layout_gravity="center"
/>
</FrameLayout>
</layout>
(注意 data
元素中声明的 variable
,以及它在 TextView 的 text
属性中的引用方式)
然后在您的自定义视图中绑定两者:
public class MyCustomView extends FrameLayout {
public MyCustomView(Context context) {
this(context, null, 0);
}
public MyCustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
MyCustomBinding binding = MyCustomBinding.inflate(inflater, this, true);
MyViewModel model = new MyViewModel("Whatever");
binding.setModel(model);
}
}
当然,在自定义视图 class 中通过 setter 传递数据可能会更好,甚至从容器视图传递(参见 http://developer.android.com/tools/data-binding/guide.html#includes)
你不需要那种类型的东西,数据绑定包括数据绑定实用程序class我们开始吧。
public MyCustomView(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
MyCustomBinding binding = DataBindingUtil.inflate(inflater, this, true);
binding.aButton.setText("Whatever");
}
这是基于最新数据绑定和 androidx 的更新答案,我来这里解决这个问题是为了解决我自己的问题,在看了上面的答案之后,我通过自己的工作代码片段开发。希望这有帮助
public class CustomActionBar1 extends RelativeLayout {
public MutableLiveData<String> title = new MutableLiveData<>("Sample text");
CustomActionBar1Binding binding;
public CustomActionBar1(Context context) {
super(context);
init(context, this);
}
public CustomActionBar1(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, this);
}
public CustomActionBar1(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, this);
}
public CustomActionBar1(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, this);
}
private void init(Context context, ViewGroup viewGroup) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
binding = DataBindingUtil.inflate(inflater, R.layout.custom_action_bar_1, viewGroup, true);
}
// helper to change title
public void changeTitle(String title) {
if (title != null)
this.title.setValue(title);
}
public void setTitleVisibility(Boolean visibile){
binding.titleText.setVisibility(visibile ? View.VISIBLE : View.INVISIBLE);
}
}
Xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="customActionBar1"
type="com.actionBar.CustomActionBar1" />
</data>
<RelativeLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:background="@color/yellow"
android:layout_height="@dimen/action_bar_height"
android:id="@+id/main_header_relative">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@{customActionBar1.title}"
android:layout_centerInParent="true"
android:gravity="center"
android:id="@+id/titleText"
android:visibility="visible"
android:textColor="@color/black" />
</RelativeLayout>
</layout>