Привязка Android XML для MutableLiveData не работает

У меня есть действие с CoordinatorLayout, которое содержит CollapsingToolbarLayout. Я привязал заголовок действия к свойству title CollapsingToolbarLayout, как показано ниже (публикация только соответствующих частей кода, поскольку макет слишком велик):

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
        <variable name="viewModel"
                  type="com.android.myapp.ui.activity.home.HomeActivityViewModel"/>
    </data>
    <RelativeLayout 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"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">

        <androidx.drawerlayout.widget.DrawerLayout
                android:id="@+id/drawerLayout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:focusableInTouchMode="true">

            <androidx.coordinatorlayout.widget.CoordinatorLayout
                    android:id="@+id/main_content"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">

                <com.google.android.material.appbar.AppBarLayout
                        android:id="@+id/app_bar_layout"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        app:layout_behavior="com.android.myapp.ui.behavior.scroll.appbar.DisableableAppBarLayoutBehavior"
                        android:fitsSystemWindows="true">

                    <com.google.android.material.appbar.CollapsingToolbarLayout
                            android:id="@+id/appbar"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:fitsSystemWindows="true"
                            app:title="@{viewModel.pageTitle}"
                            app:collapsedTitleTextAppearance="@style/CollapsedAppBarTitleStyle"
                            app:contentScrim="?attr/colorPrimary"
                            app:expandedTitleGravity="bottom|center_horizontal"
                            app:expandedTitleMarginBottom="85dp"
                            app:expandedTitleTextAppearance="@style/ExpandedAppBarTitleStyle"
                            app:layout_scrollFlags="scroll|exitUntilCollapsed">
        <!--Remaining layout-->
</layout>

Как видите, свойство pageTitle привязано к свойству xml CollapsingToolbarLayout title.

Теперь в HomeActivityViewModel:

class HomeActivityViewModel(application: Application) : AndroidViewModel(application) {
    var isToolbarExpandable = MutableLiveData<Boolean>() // For handling the expansion of toolbar on navigation. This works perfectly
    var pageTitle = MutableLiveData<String>()

    init {
        isToolbarExpandable.value = true
        pageTitle.value = "Home"
    }
}

И в HomeActivity:

class HomeActivity : AppCompatActivity() {
    private lateinit var homeViewModel: HomeActivityViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = DataBindingUtil.setContentView<ActivitySafaricomHomeBinding>(this, R.layout.activity_safaricom_home)
        binding.lifecycleOwner = this
        setSupportActionBar(toolbar)
        homeViewModel = getHomeViewModel()
        binding.viewModel = homeViewModel
    }

    private fun getHomeViewModel(): HomeActivityViewModel = ViewModelProviders.of(this).get(HomeActivityViewModel::class.java)
}

В этом случае заголовок страницы установлен правильно. Но проблема начинается, когда я пытаюсь установить заголовок в любое время после создания Activity и первого дочернего фрагмента (я использую NavHostFragment, поэтому первый фрагмент создается и прикрепляется, как только создается действие). Единственное место, где я могу изменить заголовок, - это onCreate методы активности и onCreate жизненного цикла начального фрагмента. Я использую модель просмотра как общую модель просмотра, чтобы изменить заголовок всех дочерних фрагментов. Я получаю ViewModel во фрагментах, используя:

ViewModelProviders.of(activity!!).get(HomeActivityViewModel::class.java)

После этого, когда я пытаюсь изменить заголовок, он просто не меняется. Будь то нажатие кнопки, после задержки, на следующем фрагменте ничего не работает. Единственное рабочее место - это onCreate Activity до onCreateView первого фрагмента. Я добавил наблюдателя для pageTitle в HomeActivity, но после первого изменения даже наблюдатель не запускается. При отладке я мог видеть, что извлекается тот же экземпляр модели представления, и фактически pageTitle изменяется, но он просто перестает наблюдать после создания. Есть идеи, в чем проблема? Пожалуйста помоги.


comment
вы пытались отладить сгенерированный код, в котором используется CollapsingToolbarLayout#setTitle(CharSequence title)?   -  person pskink    schedule 09.05.2019
comment
@pskink Я проверил сейчас и выяснил, что @Override protected void executeBindings() тоже не вызывается второй раз.   -  person Harikrishnan    schedule 09.05.2019
comment
почему не называется?   -  person pskink    schedule 09.05.2019
comment
Как я уже упоминал, наблюдатель, который я добавил в Activity, также не вызывается после создания. Следовательно, я думаю, что все просто перестает наблюдать изменяемые живые данные pageTitle. Который я понятия не имею, почему.   -  person Harikrishnan    schedule 09.05.2019


Ответы (1)


LiveData не работает с DataBinding, поскольку у него нет жизненного цикла.

После

binding.viewModel = homeViewModel

Попробуйте добавить

binding.lifecycleOwner = this

Итак, все вместе

binding.viewModel = homeViewModel
binding.lifecycleOwner = this
person theapache64    schedule 09.05.2019
comment
Я тоже пробовал это вчера, не сработало. Обновим вопрос. - person Harikrishnan; 09.05.2019
comment
Можно ли как-нибудь поделиться образцом проекта по этому вопросу? - person theapache64; 09.05.2019
comment
Если вы не установите владельца жизненного цикла, вы получите только одно изменение состояния, как описано. Это правильный ответ. - person Rob Gorman; 01.09.2019