i have the situation that i have a fragment, whose textfields will be filled by either a X1Object or a X2Object, which both are implementing the interface IXObject and extending the BaseObservable class provided by the Android DataBinding library, but contain additional different fields and behaviour. The IXObject contains the methods for getters and setters.
public interface IXObject {
void setName(String name);
String getName();
}
public class X1Object extends BaseObservable implements IXObject {
private String name;
@Override
@Bindable
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
}
public class X2Object extends BaseObservable implements IXObject {...}
Then i am trying to use a single layout file for the fragment, using Android DataBinding. The layout looks like this:
<?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="xObject" type="com.test.x.model.IXObject"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{xObject.name}"/>
</LinearLayout>
</layout>
In the fragment class, i am applying the binding:
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
MyFragmentBinding binding = DataBindingUtil.inflate(inflater, R.layout.my_fragment, container, false);
View view = binding.getRoot();
IXObject xobj = new X1Object();
binding.setXObject(xobject);
return view;
}
Unfortunately, using the IXObject as data binding reference, the method "addOnPropertyChangedCallback" in the BaseObservable class is never called.
Using X1Object directly for binding in the layout file and the binding class, everything works perfectly.
Can you help me how to achieve my goal to use an interface for binding?
Thank you.
Bind UI to data from data models You need to deploy a data model in order to bind to data. Clone the Home example. With Amplify Studio you can bind elements in your UI component to actual backend data from your database by passing component properties with a Data model type down to the child elements.
Data Binding allows you to effortlessly communicate across views and data sources. This pattern is important for many Android designs, including model view ViewModel (MVVM), which is currently one of the most common Android architecture patterns.
Conversely, view binding has the following limitations compared to data binding: View binding doesn't support layout variables or layout expressions, so it can't be used to declare dynamic UI content straight from XML layout files. View binding doesn't support two-way data binding.
When you declare a variable in your layout file you must take it literally. interfaces are not objects. I know Java supports generic inline objects where you can declare an interface as if it were an object, but in general they are not objects.
So when you say to the layout file to use a variable of the interface type, it really can't do much as it is not an object.
One thing you will notice and hate about android data binding is that it cannot infer types. So if you are trying to set a variable using an implementing class, but hoped to do it with an interface you will not have any luck.
You need to specify the class that will be used, not the interface that those classes inherit from. As the other answer pointed out, you can utilize a base class if your base class has the necessary methods.
Also quick note you can simply put the binding on the private member variable and it will still go through the getter and setters automatically.
The only other thing you could do is create an adapter that takes the interface or your interface or even Any with a cast, and sets the name for you. Which requires one more adapter in your already growing adapters class, but at least they are straight forward to do.
I also can not find the way to make it work with interface but I think you can use Abstract class like this.
public abstract class IXObject extends BaseObservable {
public abstract void setName(String name);
@Bindable
public abstract String getName();
}
.
public class X1Object extends IXObject {
private String name;
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
}
.
final IXObject xobj = new X1Object();
xobj.setName("nguyen");
binding.setXObject(xobj);
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