Per this comment and the Android Data Binding tutorial I should have a context
variable available when data binding:
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.
I'm using a class extending BaseObservable
to set my data, but no matter how I try to bring in the context
variable in my @Bindable
method I get the compile time error:
java.lang.RuntimeException: failure, see logs for details. @Bindable associated with method must follow JavaBeans convention getStyledName(android.content.Context)
As far as I can tell, I am following JavaBeans conventions. I've tracked the error down to this line in BrUtil but that didn't give me much help either.
I've tried changing my method and parameter names, I've tried adding in a <variable>
for the context
and a <import>
for android.content.Context
, but none of that made any difference. My User.java
below has two @Bindable
methods, the bare getName()
works fine but the one that tries to use the context
variable doesn't, so I don't think it's an issue with the rest of my data binding setup either.
Relevant code:
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);
}
I don't know whether this is a bug or intended behavior, but I observed this behavior myself, so you're not crazy.
A workaround is to create a method that is NOT marked @Bindable
in your User -- the one that requires the Context. This method won't be subject to the JavaBeans naming conventions.
Important: In order to make sure it's updated appropriately, it should take as inputs any @Bindable fields that might change.
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
}
}
and in your layout:
<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)}" />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With