Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/227.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 数据绑定&x2B;LiveData无法处理复杂的嵌套对象_Android_Android Databinding_Android Livedata - Fatal编程技术网

Android 数据绑定&x2B;LiveData无法处理复杂的嵌套对象

Android 数据绑定&x2B;LiveData无法处理复杂的嵌套对象,android,android-databinding,android-livedata,Android,Android Databinding,Android Livedata,我在LiveData和数据绑定库中遇到了一些意想不到的行为。 我已经实现了这个答案中的CustomLiveData,所以我可以在父类中调用notifyChange()来更新UI 我有父对象(为了简洁起见省略了一些方法): 问题是,当我更改一天的任务字段中的项目时,来自item\u main\u screen\u task.xml的数据绑定没有更新,例如调用方法start(),但其他字段,如state,确实正确更新,因此我猜问题在于它里面的列表 fragment_main_screen.xml,r

我在LiveData和数据绑定库中遇到了一些意想不到的行为。 我已经实现了这个答案中的CustomLiveData,所以我可以在父类中调用notifyChange()来更新UI

我有父对象(为了简洁起见省略了一些方法):

问题是,当我更改一天的任务字段中的项目时,来自item\u main\u screen\u task.xml的数据绑定没有更新,例如调用方法start(),但其他字段,如state,确实正确更新,因此我猜问题在于它里面的列表

fragment_main_screen.xml,recyclerview用Day class字段任务填充:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <import type="android.view.View"/>

        <variable
            name="viewmodel"
            type="com.sillyapps.meantime.ui.mainscreen.MainViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorPrimary">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/tasks"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="16dp"
            android:visibility="@{viewmodel.noTemplate ? View.GONE : View.VISIBLE}"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            app:layout_constraintBottom_toTopOf="@+id/play_button"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/constraintLayout"
            tools:listitem="@layout/item_main_screen_task"
            tools:visibility="visible" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

item_main_screen_task,taskState属性基本上就是根据一天的状态设置背景可绘制的属性

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="task"
            type="com.sillyapps.meantime.data.RunningTask" />

        <variable
            name="taskAdapterPosition"
            type="Integer" />

        <variable
            name="clickListener"
            type="com.sillyapps.meantime.ui.ItemClickListener" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        app:taskState="@{task.state}"

        android:onClick="@{() -> clickListener.onClickItem(taskAdapterPosition)}">

        <TextView
            android:id="@+id/time"
            style="@style/TimeItemStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginBottom="8dp"
            android:text="@{task.uiStartTime}"

            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/enter_name"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="17:00" />

        <TextView
            android:id="@+id/enter_name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"

            android:layout_marginStart="8dp"
            android:layout_marginEnd="8dp"

            android:text="@{task.name}"
            app:layout_constraintBottom_toBottomOf="@+id/time"
            app:layout_constraintEnd_toStartOf="@+id/progress"
            app:layout_constraintStart_toEndOf="@+id/time"
            app:layout_constraintTop_toTopOf="@+id/time"
            tools:text="Свободное время" />

        <TextView
            android:id="@+id/progress"
            style="@style/TimeItemStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_marginEnd="8dp"

            android:text="@{task.timeRemain}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/enter_name"
            app:layout_constraintTop_toTopOf="@+id/time"
            tools:text="01:00" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>


提前感谢。

结果表明,解决方案非常简单,但有些出乎意料

子类应该扩展BaseObservable,并在每个数据绑定字段的setter上调用notifyChange(),如下所示:

class RunningTask(
    startTime: Long,

    var name: String = "",
    private val originalDuration: Long = 0L,

    val sound: String
): BaseObservable() {
    var startTime: Long = startTime
        set(value) {
            field = value
            uiStartTime = convertMillisToStringFormat(value)
        }

    @Bindable
    var uiStartTime: String = convertMillisToStringFormat(startTime)
        set(value) {
            field = value
            notifyPropertyChanged(BR.uiStartTime)
        }

    var state: State = State.WAITING
        set(value) {
             field = value
             notifyChange()
        }
    
    ...
}

在提出问题之前,我似乎已经在uiStartTime中实现了这一点,但我只是不知道它起作用的确切原因。

结果表明,解决方案非常简单,但有些出乎意料

子类应该扩展BaseObservable,并在每个数据绑定字段的setter上调用notifyChange(),如下所示:

class RunningTask(
    startTime: Long,

    var name: String = "",
    private val originalDuration: Long = 0L,

    val sound: String
): BaseObservable() {
    var startTime: Long = startTime
        set(value) {
            field = value
            uiStartTime = convertMillisToStringFormat(value)
        }

    @Bindable
    var uiStartTime: String = convertMillisToStringFormat(startTime)
        set(value) {
            field = value
            notifyPropertyChanged(BR.uiStartTime)
        }

    var state: State = State.WAITING
        set(value) {
             field = value
             notifyChange()
        }
    
    ...
}
在提出问题之前,我似乎已经在uiStartTime中实现了这个功能,但我只是不知道它工作的确切原因

class RunningTask(
    startTime: Long,

    var name: String = "",
    private val originalDuration: Long = 0L,

    val sound: String
): BaseObservable() {
    var startTime: Long = startTime
        set(value) {
            field = value
            uiStartTime = convertMillisToStringFormat(value)
        }

    @Bindable
    var uiStartTime: String = convertMillisToStringFormat(startTime)
        set(value) {
            field = value
            notifyPropertyChanged(BR.uiStartTime)
        }

    var state: State = State.WAITING
        set(value) {
             field = value
             notifyChange()
        }
    
    ...
}