尝试将数据绑定提供的上下文变量与 BaseObservable 一起使用时出错
Error when attempting to use the data binding provided context variable with BaseObservable
根据 and the Android Data Binding tutorial 我应该在数据绑定时有一个可用的 context
变量:
A special variable named context is generated for use in binding expressions as needed. The value for context is the Context from the root View's getContext(). The context variable will be overridden by an explicit variable declaration with that name.
我正在使用 class 扩展 BaseObservable
来设置我的数据,但无论我如何尝试在我的 @Bindable
方法中引入 context
变量我收到编译时错误:
java.lang.RuntimeException: failure, see logs for details.
@Bindable associated with method must follow JavaBeans convention getStyledName(android.content.Context)
据我所知,我遵循 JavaBeans 约定。我已将错误追踪到 this line in BrUtil,但这也没有给我太多帮助。
我试过更改我的方法和参数名称,我试过为 context
添加 <variable>
和为 android.content.Context
添加 <import>
,但是none 其中有任何不同。我下面的 User.java
有两个 @Bindable
方法,裸 getName()
可以正常工作,但是尝试使用 context
变量的方法没有,所以我认为这不是我的其余数据绑定设置也有问题。
相关代码:
activity_main.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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable name="user" type="com.kasra.androidsandbox.User" />
</data>
<LinearLayout
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/main_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<TextView
android:id="@+id/main_textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@{user.getStyledName(context)}" />
</LinearLayout>
</layout>
User.java
:
public class User extends BaseObservable {
private String name;
public User(String name) {
this.name = name;
}
@Bindable
public String getName() {
return this.name;
}
@Bindable
public CharSequence getStyledName(Context ctx) {
int color = ctx.getResources().getColor(R.color.branded_pink);
Spannable textSpan = new SpannableString(name);
textSpan.setSpan(new ForegroundColorSpan(color), 0, textSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return textSpan;
}
}
MainActivity.java
:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User user = new User("Kasra");
binding.setUser(user);
Toolbar toolbar = (Toolbar) findViewById(R.id.main_toolbar);
setSupportActionBar(toolbar);
}
我不知道这是一个错误还是有意为之的行为,但我自己观察到了这种行为,所以你没有疯。
一种解决方法是在您的用户中创建一个未标记 @Bindable
的方法——需要上下文的方法。此方法不受 JavaBeans 命名约定的约束。
重要:为了确保它得到适当更新,它应该将任何可能更改的@Bindable 字段作为输入。
User.java
public class User extends BaseObservable {
private String name;
public User(String name) {
this.name = name;
}
@Bindable
public String getName() {
return this.name;
}
public CharSequence getStyledName(Context ctx, String name) {
// construct styled name here
}
}
在您的布局中:
<TextView
android:id="@+id/main_textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@{user.getStyledName(context, user.name)}" />
自 Android 2.3
起,您可以在 @Bindable
注释中声明可绑定依赖的字段。
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Bindable {
String[] value() default {};
}
在你的例子中,你会这样写你的函数
@Bindable("name")
public CharSequence getStyledName(Context ctx) {
// your existing code
}
见https://medium.com/google-developers/android-data-binding-dependent-properties-516d3235cd7c
我的实验是你只能在不接受参数的方法中使用@Bindable。例如:
@Bindable
public String getName() {
...
}
<TextView>
android:text="@{myClass.name}"
</TextView>
当我的方法看起来像这样时,我遇到了这个问题
@Bindable
public Boolean isRead() {
return read;
}
当我将函数的 return 类型更改为基本类型时,它解决了。也许对某人有用。
@Bindable
public boolean isRead() {
return read;
}
我喜欢这个
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
singleton = this
}
companion object {
private var singleton: MyApplication? = null
fun getInstance(): MyApplication? {
return singleton
}
}}
清单文件中的更改
<application
android:name=".other.MyApplication">
</application>
在 class 中定义 baseurl 等的创建方法。
fun getResourceString(resourceId: Int): String? {
return MyApplication
.getInstance()!!
.resources
.getString(resourceId)
}
现在在BaseObservable中使用了这个方法class
@Bindable
var email:String?=""
set(value) {
field = value
notifyPropertyChanged(BR.email)
notifyPropertyChanged(BR.emailError)
}
@get:Bindable
val emailError: String?
get() = if (email == null || email.toString().trim().isEmpty() || !Patterns.EMAIL_ADDRESS.matcher(email.toString().trim()).matches())
{
AppUtil.getResourceString(R.string.enter_valid_email)
} else {
null
}
并在 xml 文件中
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/txtLoginEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorTextAppearance="@style/error_appearance"
android:hint="@string/email"
android:text="@={loginUser.email}"
app:error="@{loginUser.emailError}"/>
希望这篇能帮到你..!
根据 context
变量:
A special variable named context is generated for use in binding expressions as needed. The value for context is the Context from the root View's getContext(). The context variable will be overridden by an explicit variable declaration with that name.
我正在使用 class 扩展 BaseObservable
来设置我的数据,但无论我如何尝试在我的 @Bindable
方法中引入 context
变量我收到编译时错误:
java.lang.RuntimeException: failure, see logs for details. @Bindable associated with method must follow JavaBeans convention getStyledName(android.content.Context)
据我所知,我遵循 JavaBeans 约定。我已将错误追踪到 this line in BrUtil,但这也没有给我太多帮助。
我试过更改我的方法和参数名称,我试过为 context
添加 <variable>
和为 android.content.Context
添加 <import>
,但是none 其中有任何不同。我下面的 User.java
有两个 @Bindable
方法,裸 getName()
可以正常工作,但是尝试使用 context
变量的方法没有,所以我认为这不是我的其余数据绑定设置也有问题。
相关代码:
activity_main.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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable name="user" type="com.kasra.androidsandbox.User" />
</data>
<LinearLayout
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/main_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<TextView
android:id="@+id/main_textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@{user.getStyledName(context)}" />
</LinearLayout>
</layout>
User.java
:
public class User extends BaseObservable {
private String name;
public User(String name) {
this.name = name;
}
@Bindable
public String getName() {
return this.name;
}
@Bindable
public CharSequence getStyledName(Context ctx) {
int color = ctx.getResources().getColor(R.color.branded_pink);
Spannable textSpan = new SpannableString(name);
textSpan.setSpan(new ForegroundColorSpan(color), 0, textSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return textSpan;
}
}
MainActivity.java
:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User user = new User("Kasra");
binding.setUser(user);
Toolbar toolbar = (Toolbar) findViewById(R.id.main_toolbar);
setSupportActionBar(toolbar);
}
我不知道这是一个错误还是有意为之的行为,但我自己观察到了这种行为,所以你没有疯。
一种解决方法是在您的用户中创建一个未标记 @Bindable
的方法——需要上下文的方法。此方法不受 JavaBeans 命名约定的约束。
重要:为了确保它得到适当更新,它应该将任何可能更改的@Bindable 字段作为输入。
User.java
public class User extends BaseObservable {
private String name;
public User(String name) {
this.name = name;
}
@Bindable
public String getName() {
return this.name;
}
public CharSequence getStyledName(Context ctx, String name) {
// construct styled name here
}
}
在您的布局中:
<TextView
android:id="@+id/main_textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@{user.getStyledName(context, user.name)}" />
自 Android 2.3
起,您可以在 @Bindable
注释中声明可绑定依赖的字段。
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Bindable {
String[] value() default {};
}
在你的例子中,你会这样写你的函数
@Bindable("name")
public CharSequence getStyledName(Context ctx) {
// your existing code
}
见https://medium.com/google-developers/android-data-binding-dependent-properties-516d3235cd7c
我的实验是你只能在不接受参数的方法中使用@Bindable。例如:
@Bindable
public String getName() {
...
}
<TextView>
android:text="@{myClass.name}"
</TextView>
当我的方法看起来像这样时,我遇到了这个问题
@Bindable
public Boolean isRead() {
return read;
}
当我将函数的 return 类型更改为基本类型时,它解决了。也许对某人有用。
@Bindable
public boolean isRead() {
return read;
}
我喜欢这个
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
singleton = this
}
companion object {
private var singleton: MyApplication? = null
fun getInstance(): MyApplication? {
return singleton
}
}}
清单文件中的更改
<application
android:name=".other.MyApplication">
</application>
在 class 中定义 baseurl 等的创建方法。
fun getResourceString(resourceId: Int): String? {
return MyApplication
.getInstance()!!
.resources
.getString(resourceId)
}
现在在BaseObservable中使用了这个方法class
@Bindable
var email:String?=""
set(value) {
field = value
notifyPropertyChanged(BR.email)
notifyPropertyChanged(BR.emailError)
}
@get:Bindable
val emailError: String?
get() = if (email == null || email.toString().trim().isEmpty() || !Patterns.EMAIL_ADDRESS.matcher(email.toString().trim()).matches())
{
AppUtil.getResourceString(R.string.enter_valid_email)
} else {
null
}
并在 xml 文件中
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/txtLoginEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorTextAppearance="@style/error_appearance"
android:hint="@string/email"
android:text="@={loginUser.email}"
app:error="@{loginUser.emailError}"/>
希望这篇能帮到你..!