Passing LiveData as <layout> tag argument

Viewed 1104

I have quick question about my code. I'm writing an app using Android MVVM with LiveData. I want to create loading layout which is will be included in many views. Main goal is to have ability of passing live data representing if layout should be visible and what text info should be displayed with progress bar.

So far I created loading indicator layout, and definded two variables "indicatorVisibility" and "progressText". In attached code one of values is commented out. I created also BindingAdapters to set visibility and text on controls.

This is my layout with progress bar

<data>

    <variable
        name="indicatorVisibility"
        type="android.arch.lifecycle.LiveData"/>
    <!--<variable-->
        <!--name="progressText"-->
        <!--type="android.arch.lifecycle.LiveData"/>-->
</data>


<android.support.constraint.ConstraintLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/layout_loading_background"
    >

    <ProgressBar
        android:id="@+id/progressBar2"
        style="?android:attr/progressBarStyle"
        android:layout_width="@dimen/layout_loading_progress_bar_size"
        android:layout_height="@dimen/layout_loading_progress_bar_size"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/textView7"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <!--android:text="@{progressText}"-->

    <TextView
        android:id="@+id/textView7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:text="TextView"
        android:textColor="@color/layout_loading_text"
        android:textSize="@dimen/layout_loading_text_size"
        app:layout_constraintBottom_toBottomOf="@+id/progressBar2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/progressBar2"
        app:layout_constraintTop_toTopOf="@+id/progressBar2" />
</android.support.constraint.ConstraintLayout>

This is how i include it in fragment layout

<include layout="@layout/layout_loading_info"
            app:indicatorVisibility="@{viewModel.isBusy}"
            />

And those are my bind adapters:

@BindingAdapter("android:visibility")
fun getVisibility(view: View, liveData: LiveData<Boolean>){
        liveData.observe(view.getLifecycleOwner(), Observer {
        view.visibility = if(it == true) View.VISIBLE else View.INVISIBLE
    })
}

@BindingAdapter("app:text")
fun getText(view: TextView, liveData : LiveData<Int>)
{
    liveData.observe(view.getLifecycleOwner(), Observer {
         it?.let{
            view.text = view.context.resources.getString(it)
        }
    })
}

So far I tried passing simple types like Integer and it works. The problem lays in LiveData. Even when I don't use variables inside included layout I get error (error message tells nothing).

I saw similar stack task [here] : Applying databinding adapter to include tag but they passed the whole viewModel, which is not a flexible enough solution for me.

1 Answers

I think you use the wrong name-space; for data-binding that should be bind:

<include
    layout="@layout/layout_loading_info"
    bind:indicatorVisibility="@{viewModel.isBusy}"/>

The data-type is LiveData<Boolean>; therefore you'd need to import LiveData and Boolean, in order to use them in a variable definition. The data-binding should look about like this:

<data class=".databinding.LiveDataBinding">
    <import type="android.arch.lifecycle.LiveData"/>
    <import type="java.lang.Boolean"/>
    <variable name="indicatorVisibility" type="LiveData&lt;Boolean&gt;"/>
</data>

bind:viewModel="@{viewModel}" might in general be better than binding single values.

Related