Поведение привязки данных прерывается после перехода от действия к фрагменту - PullRequest
0 голосов
/ 11 сентября 2018

недавно я играл с библиотекой компонентов архитектуры Android и привязки данных, и я столкнулся с действительно странным случаем, и после поисков в Интернете и проб в течение нескольких дней я решил прийти сюда за помощью.

У меня есть фрагмент в действии, и я должен сделать setLifeCycleOwner(fragment) для привязки фрагмента, что делает осведомленным о жизненном цикле привязки.И есть флажок и кнопка во фрагменте, где:
Checkbox текст должен быть изменен на основе статуса проверки
Button обратный вызов запускает действие B через statrActivityForResult

Проблема, с которой я сталкиваюсь, заключается в том, что при возвращении из действия B отображаемый флажок текст больше не обновляется.
Я проверил обратный вызов для флажка (onCheckedChanged), обратный вызов работает нормально, и модельдля отображения текста также обновляется. Каким-то образом привязка данных не получает событие изменения поля, поэтому пользовательский интерфейс не обновляется.

У кого-нибудь была или была эта проблема?или что-то, что я пропустил, проверяя?
Если есть какая-либо информация, которую я должен предоставить, пожалуйста, дайте мне знать.Большое спасибо за помощь!


Вот примеры, которые связаны с делом:

activity.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <FrameLayout
        android:id="@+id/main_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</layout>

frag_test.xml

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

    <data>

        <variable
            name="viewModel"
            type="za.co.travelstart.flapp.activities.test.TestViewModel" />
    </data>

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include
            layout="@layout/section_test"
            bind:viewModel="@{viewModel}" />
    </android.support.constraint.ConstraintLayout>
</layout>

section_test.xml

<?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">

    <data>

        <variable
            name="viewModel"
            type="za.co.travelstart.flapp.activities.test.TestViewModel" />
    </data>

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <CheckBox
            android:id="@+id/checkBox"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onCheckedChanged="@{(compoundButton, isChecked) -> viewModel.onCheckBoxCheckedChanged(isChecked)}"
            android:text="@{viewModel.testModel.checkBoxText}"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{(v) -> viewModel.onButtonClicked()}"
            android:text="Start Test B"
            app:layout_constraintTop_toBottomOf="@id/checkBox" />
    </android.support.constraint.ConstraintLayout>
</layout>

TestActivity.kt

class TestActivity : ParentActivity() {

    // View Model
    private lateinit var mViewModel: TestViewModel

    /* ------------------------------- Life Cycle */

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // init view model
        initViewModel()
        // init binding
        initBinding()
        // observe data
        observeData()
        // init fragment utils
        initFragmentUtils()
        // display fragment
        displayFragment()
    }

    override fun onActivityResult(requestCode: Int,
                                  resultCode: Int,
                                  data: Intent?) {
        when (requestCode) {
            1337 -> {
                // do nothing
            }
        }
    }

    /* ------------------------------- Methods */

    /**
     * Init view model
     */
    private fun initViewModel() {
        mViewModel = ViewModelProviders
                .of(this)
                .get(TestViewModel::class.java)
    }

    /**
     * Init binding
     */
    private fun initBinding() {
        DataBindingUtil.setContentView<ActivityTestBinding>(
                this, R.layout.activity_test).apply {
            setLifecycleOwner(this@TestActivity)
        }
    }

    /**
     * Observe the data in view model
     */
    private fun observeData() {
        mViewModel.buttonTriggerLiveData.observe(this, Observer {
            // navigate to test b
            navigateToTestB()
        })
    }

    /**
     * Display test fragment
     */
    private fun displayFragment() {
        fragmentUtils.displayTest()
    }

    /**
     * Navigate to test B
     */
    private fun navigateToTestB() {
        startActivityForResult(Intent(this, TestActivityB::class.java), 1337)
    }
}

TestFragment.kt

class TestFragment : Fragment() {

    // View Model
    private lateinit var mViewModel: TestViewModel

    // Binding
    private lateinit var mBinding: FragmentTestBinding

    /* ------------------------------ Instance Factory */

    companion object {

        /**
         * Instance factory
         */
        fun newInstance() = TestFragment()
    }

    /* ------------------------------ Life Cycle */

    override fun onCreateView(inflater: LayoutInflater,
                              container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // init view model
        initViewModel()
        // init data binding
        initBinding(inflater, container)
        // return binding root view
        return mBinding.root
    }

    /* ------------------------------ Methods */

    /**
     * Init view model
     */
    private fun initViewModel() {
        activity?.also {
            mViewModel = ViewModelProviders
                    .of(it)
                    .get(TestViewModel::class.java)
        }
    }

    /**
     * Init binding
     */
    private fun initBinding(inflater: LayoutInflater,
                            container: ViewGroup?) {
        mBinding = DataBindingUtil.inflate(
                inflater, R.layout.fragment_test, container, false)
        mBinding.apply {
            viewModel = mViewModel
            setLifecycleOwner(this@TestFragment)
        }
    }
}

TestViewModel.kt

class TestViewModel : ViewModel() {

    // Data
    val testModel: MutableLiveData<TestModel> = MutableLiveData()

    // Button callback trigger
    val buttonTriggerLiveData: MutableLiveData<Boolean> = MutableLiveData()

    init {
        testModel.value = TestModel()
    }

    /**
     * Callback for checkbox
     */
    fun onCheckBoxCheckedChanged(isChecked: Boolean) {
        testModel.value?.checkBoxText = if (isChecked) "checked" else "unchecked"
    }

    /**
     * Callback for button
     */
    fun onButtonClicked() {
        buttonTriggerLiveData.value = true
    }
}

TestModel.kt

class TestModel : BaseObservable() {
    var checkBoxText = "unclicked"
        @Bindable get() = field
        set(value) {
            field = value
            notifyPropertyChanged(BR.checkBoxText)
        }
}
...