недавно я играл с библиотекой компонентов архитектуры 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)
}
}