最近,我正在使用Android Architecture Component和Data Binding库,并且遇到了一个非常奇怪的案例,在网络上搜索并尝试了几天后,我决定来这里寻求帮助。
我在一个活动中有一个片段,并且我对片段的绑定进行了setLifeCycleOwner(fragment)
,这使绑定的生命周期有了知觉。片段中有一个复选框和一个按钮,其中:
Checkbox
的文本应根据检查状态进行更改
Button
回调通过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>
fragment_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)
}
}