Live Data Observer On 按钮 屏幕旋转时单击
Posted
技术标签:
【中文标题】Live Data Observer On 按钮 屏幕旋转时单击【英文标题】:Live Data Observer On Button Click when screen rotataed 【发布时间】:2021-02-26 10:26:54 【问题描述】:我想知道按钮何时点击片段并更新 MainActivity。这段代码工作正常,但是当屏幕旋转由于再次调用 Activity LifeCycle OnCreate 和 viewModel.nav.observe 再次调用新值 true,但我希望它被称为 only onButton 点击。 我需要的是 onClick 值将设置为 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()
视图模型
class SharedViewModel : ViewModel()
var nav = MutableLiveData(false)
【问题讨论】:
【参考方案1】:您可以使用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 步:在 MainActivity 中
viewModel.nav.observe(this, Observer
Log.d("DTAG", "Status: $it")
)
【讨论】:
【参考方案2】:我不喜欢这个解决方案,但this code lab 说,您应该将“导航处理”事件发布回视图模型。
查看模型实现:
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()
)
【讨论】:
【参考方案3】:只需使用saveStateViewMode,文档here
【讨论】:
以上是关于Live Data Observer On 按钮 屏幕旋转时单击的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript--- .bind() .live() .delegate() .on()的区别
jQuery中.bind() .live() .delegate() .on()的比较