How to define a generic type of a data binding variable?
The following code never compiles.
<data>
<variable
name="viewModel"
type="com.example.viewmodel.ViewModel<Model>"/>
</data>
You need to escape <Model> as shown below:
<data>
<variable
name="viewModel"
type="com.example.viewmodel.ViewModel<Model>"/>
</data>
Android Studio will still show a "Cannot resolve symbol" error, but the XML will compile. It is a known issue. From Android Studio Support for Data Binding:
Note: Arrays and generic types, such as the Observable class, might display errors when there are no errors.
Try this one:
<data>
<variable
name="viewModel"
type="com.example.viewmodel.ViewModel<Model>"/>
</data>
< is responsible for < and > is responsible for >.
You can set something like examples above:
<data>
<import type="com.example.path.Model"/>
<variable
name="obj"
type="com.example.viewmodel.ViewModel<Model>"
/>
</data>
NOTE: you can write '>' or '>' at end of Model should be OK
To avoid error display do not forget to add line to tell what object type is used:
<import type="com.example.path.Model"/>
You have a left triangle bracket in XML; XML don't play that way. try
<data>
<variable
name="viewModel"
type="com.example.viewmodel.ViewModel<Model>"/>
</data>
Related
Code A can work well, I don't know why Code b can't work, could you tell me ?
Code A
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="androidx.lifecycle.LiveData" />
<variable
name="MyValue1"
type="LiveData<Integer>" />
</data>
...
Code B
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="androidx.lifecycle.LiveData" />
<variable
name="MyValue2"
type="LiveData<Int>" />
</data>
...
Because Int is not part of Expression language for data binding
can not assign the Java's primitive type to LiveData
class of Int is not available on Java but Kotlin does
class of Integer is available on Java but Kotlin doesn't
class of Int on Kotlin is not a primitive type, this is a wrapper class for int so we can assign Int type to LiveData
As i'm new to data-binding, can Anyone help to fix this.
Here is my Fragment
Here is my Layout
Here is my gradle
Here is my ViewModel
Change the variable name of your LoginViewModel from data to viewModel.
For Example:
<data>
<variable name="viewModel" type="com.xxx.yyy.ui.login.LoginViewModel" />
</data>
After that Rebuild your project
I'm trying to assign a behavior different than the standard one when my swipelayout is refreshed:
This is my code:
binding.refreshed = binding.refreshOtrosRequestList
binding.refreshOtrosRequestList!!.setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener {
[Change behavior]
})
These are the elements I'm using defined in the corresponding XML file:
<data>
<variable name="refreshed" type="androidx.swiperefreshlayout.widget.SwipeRefreshLayout"/>
</data>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/refreshOtrosRequestList"
app:onRefreshListener="#{() -> model.onRefresh(refreshed)}"
android:layout_width="wrap_content"
android:layout_height="match_parent">
But the defined setOnRefreshListener never fires:
What am I doing wrong?
PD: this is request, also in data in XML file:
<data>
<variable name="model" type="es.nscontrol.controlpresencial.viewmodels.NonWorkingDateViewModel"/>
<variable name="refreshed" type="androidx.swiperefreshlayout.widget.SwipeRefreshLayout"/>
</data>
What is "model"?
model.onRefresh(refreshed)
Is it somewhere defined?
Additionally, it looks strange when you use databiding to store view from this layout in a variable.
Edit:
I hope you also binded this "model" to the actual variable as you did with
binding.refreshed = binding.refreshOtrosRequestList
And invoke this after you binded these variables:
binding.executePendingBindings()
<layout>
<data>
<variable
name="viewModel"
type="com.foo.ViewModel"/>
</data>
...
<include
layout="#layout/widget_parents_details"
android:visibility="#{viewModel.fooVisibility}"/>
...
</layout>
class ViewModel: ViewModel() {
val fooVisibility = MutableLiveData(View.GONE)
}
The problem is that this android:visibility="#{viewModel.fooVisibility}" works fine in other Views including <LinearLayout>. However, when it is used in tag, it returns below error
error: incompatible types: MutableLiveData<Integer> cannot be converted to int
in databinding of android simply i want to control view visibility by checking viewmodel parameter as profilePicUrl
Solution 1:
when profilePicUrl is empty view should be gone, otherwise that should be visible, for example:
<data>
<import type="android.view.View"/>
<import type="android.text.TextUtils"/>
<variable name="viewModel" type="xx.xxxxx.xxxxxxx.MyViewModel"/>
</data>
...
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="#{TextUtils.isEmpty(viewModel.profilePicUrl) ? View.GONE : View.VISIBLE}"
>
i get this error:
error: '#{TextUtils.isEmpty(viewModel.profilePicUrl)? View.GONE : View.VISIBLE' is incompatible with attribute visibility (attr) enum [gone=2, invisible=1, visible=0].
Solution 2:
after getting this error i try to test another solution to approach that, for example:
BindingAdapters class:
object BindingAdapters {
#BindingAdapter("visibleIf")
#JvmStatic
fun changeVisibility(#NonNull imageView: ImageView, visible: Boolean) {
if (visible) {
imageView.visibility = View.VISIBLE
} else {
imageView.visibility = View.GONE
}
}
}
xml layout:
<data>
<import type="android.view.View"/>
<import type="android.text.TextUtils"/>
<variable name="viewModel" type="xx.xxxxx.xxxxxxx.MyViewModel"/>
</data>
...
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:visibleIf="#{TextUtils.isEmpty(viewModel.profilePicUrl)}"
>
i get this error:
error: attribute visibleIf (aka xxx.xxxxx.xxxxxxxx:visibleIf) not found.
Are you sure you have enabled data-binding properly? Your code is correct, so there is no reason why it shouldn't work.
Please make sure this code is added in the Gradle file of your app module:
dataBinding {
enabled = true
}
In addition, I would recommend adding this to the gradle.properties file:
android.databinding.enableV2=true
Here you can see a similar question.
Regarding the second solution, sometimes importing the object that contains the adapter methods helps:
<import type="com.your.package.name.BindingAdapters" />
Also, please make sure you have added this attribute on your layout tag:
xmlns:app="http://schemas.android.com/apk/res-auto"