英文:
Context is null in Lifecycle aware LiveEvent
问题
以下是您要翻译的内容:
我的项目目前正在使用以下的SingleLiveEvent
实现。
class SingleLiveEvent<T>(
private val allowMultipleObservers: Boolean = false
) : MutableLiveData<T>() {
private val mPending = AtomicBoolean(false)
private val observers = mutableSetOf<Observer<in T>>()
@MainThread
override fun observe(
owner: LifecycleOwner,
observer: Observer<in T>
) {
if (!allowMultipleObservers && hasActiveObservers()) {
Timber.tag(TAG)
.w("Multiple observers registered but only one will be notified of changes.")
} else {
observers.add(observer)
}
// Observe the internal MutableLiveData
super.observe(owner, Observer { t ->
if (mPending.compareAndSet(true, false)) {
observers.forEach { observer ->
observer.onChanged(t)
}
}
})
}
...
当我们在onResume
或onCreateView
内部执行以下操作时:
SingleLiveEvent.observe(viewLifecycleOwner) {
requireContext()
}
有时我们会收到一个崩溃报告,指出Context
为空。然而,requireContext()
不应该总是向我们提供一个有效的Context
值吗?因为它是附加到viewLifecycleOwner
的。
英文:
My project is currently using the following SingleLiveEvent
implementation.
class SingleLiveEvent<T>(
private val allowMultipleObservers: Boolean = false
) : MutableLiveData<T>() {
private val mPending = AtomicBoolean(false)
private val observers = mutableSetOf<Observer<in T>>()
@MainThread
override fun observe(
owner: LifecycleOwner,
observer: Observer<in T>
) {
if (!allowMultipleObservers && hasActiveObservers()) {
Timber.tag(TAG)
.w("Multiple observers registered but only one will be notified of changes.")
} else {
observers.add(observer)
}
// Observe the internal MutableLiveData
super.observe(owner, Observer { t ->
if (mPending.compareAndSet(true, false)) {
observers.forEach { observer ->
observer.onChanged(t)
}
}
})
}
...
When we do this inside of onResume
or onCreateView
SingleLiveEvent.observe(viewLifecycleOwner) {
requireContext()
}
We sometimes receive a crash saying that the Context
is null. However, shouldn't requireContext()
always give us a valid Context
value since it's attached to the viewLifecycleOwner
?
答案1
得分: 1
你的实现有缺陷 - 只要观察者以非活动状态注册(或现有观察者变为非活动状态),那么你传递给 super.observe
的观察者封装将会失败,因为你强制调用 onChanged
来处理所有观察者,而不考虑它们的实际状态。
你应该用 hasObservers()
替代 hasActiveObservers()
。但就个人而言,我会考虑使用实现了 MediatorLiveData
的解决方案,因为这个实现并没有正确处理进入已销毁状态的观察者,导致它们会永远保留在你的 observers
列表中。
英文:
Your implementation is flawed - it's possible to register multiple observers as long as they attach in inactive state (or existing observers became inactive), then observer wrapper you passed to super.observe
will fail because you're forcing a call to onChanged
for all observers disregarding their actual state.
You should replace hasActiveObservers()
with hasObservers()
. But personally I'd look into solution implementing MediatorLiveData
since this implementation doesn't properly handle observers that enter destroyed state, leaving them in your observers
list forever.
答案2
得分: 0
requireContext()
除了与getContext()
进行空指针检查比较外,并没有特别的功能。
来自谷歌的答复:
我们应该如何修复这个问题?
首先,我们应该修复潜在的错误。
- 查找所有可能在某个时刻分离片段的地方
- 修改代码,如下面的示例
在Java中:
Context context = getContext();
if (context == null) {
// 处理空上下文场景
} else {
// 带有上下文的旧代码
}
来源:https://medium.com/@shafran/fragment-getcontext-vs-requirecontext-ffc9157d6bbe
英文:
requireContext()
does nothing special except for null-check comparing to getContext()
.
Answer from Google:
How should we fix that?
Firstly we should fix potentials bugs.
- Find all places where fragment can be detached at some point of time
- Change code like in the sample below
In Java:
Context context = getContext();
if (context == null) {
// Handle null context scenario
} else {
// Old code with context
}
Source: https://medium.com/@shafran/fragment-getcontext-vs-requirecontext-ffc9157d6bbe
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论