实时数据观察员打开按钮当屏幕旋转时单击



我想知道按钮何时点击片段并更新MainActivity。此代码工作正常,但当屏幕旋转时,由于再次调用"创建时的活动生命周期"和再次调用viewModel.nav.observe并使用新值true,但我希望仅在单击按钮时调用。我需要的是单击时,值将设置为true,然后设置为false。所以我只知道按钮何时单击,而不知道屏幕上的旋转。或者通过其他方式来了解片段中的按钮被点击了。

我怎样才能做到这一点?

碎片

class Fragment1 : Fragment() {
companion object {
fun newInstance() = Fragment1()
}
private lateinit var viewModel: SharedViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_1, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)

buttonNextF1.setOnClickListener {
viewModel.nav.value = true
}
}
}

主要活动

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val viewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
var fragment1 = Fragment1.newInstance()
navigateToFragment(fragment1)
viewModel.nav.observe(this, {
Log.d("DTAG", "Status: $it")
})
}
private fun navigateToFragment(fragment: Fragment) {
val fragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.addToBackStack(null)
fragmentTransaction.replace(R.id.mainFrame, fragment)
fragmentTransaction.commit()
}
}

ViewModel

class SharedViewModel : ViewModel() {

var nav = MutableLiveData(false)
}

您可以使用SingleLiveEvent来实现您的目标,因为:

  • 您只想通知事件一次(点击片段上的按钮(
  • 只有一个观察者(MainActivity(在LiveData上进行观察

步骤1:创建SingleLiveEvent.kt文件

class SingleLiveEvent<T> : MutableLiveData<T?>() {
private val mPending = AtomicBoolean(false)
@MainThread
override fun observe(owner: LifecycleOwner, observer: Observer<in T?>) {
if (hasActiveObservers()) {
Log.w(
TAG,
"Multiple observers registered but only one will be notified of changes."
)
}
// Observe the internal MutableLiveData
super.observe(owner, Observer { t ->
if (mPending.compareAndSet(true, false)) {
observer.onChanged(t)
}
})
}
@MainThread
override fun setValue(t: T?) {
mPending.set(true)
super.setValue(t)
}
/**
* Used for cases where T is Void, to make calls cleaner.
*/
@MainThread
fun call() {
value = null
}
companion object {
private const val TAG = "SingleLiveEvent"
}
}

步骤2:在SharedViewModel 中

class SharedViewModel : ViewModel() {
var nav = SingleLiveEvent<Boolean>()
}

步骤3:在主活动中

viewModel.nav.observe(this, Observer {
Log.d("DTAG", "Status: $it")
})

我不喜欢这个解决方案,但这个代码实验室说,你应该发布"导航已处理";事件返回视图模型。

查看模型实现:

interface MyViewModel {
val navigationEvent: LiveData<Unit?>

fun onNavigationButtonClicked()
fun onNavigationDone()
}
class MyViewModelImpl : ViewModel(), MyViewModel {

override val navigationEvent = MutableLiveData<Unit?>()
override fun onNavigationButtonClicked() {
navigationEvent.value = Unit
}
override fun onNavigationDone() {
navigationEvent.value = null
}
}

查看模型使用情况

vm.navigationEvent.observe(lifecycleOwner, { event ->
// check event is not handled yet
event ?: return@observe
// make transition
findNavController().navigate(direction)
// notify view model navigation event is handled
vm.onNavigationDone()
})

只需使用saveStateViewMode,在此处记录

最新更新