NSimon,其伟大的,你开始使用AAC。
在此之前,我在aac's-github中写了一个issue。
有几种方法可以做到这一点。
一个解决办法是使用
WeakReference到NavigationController其保持活动的语境。这是处理ViewModel中的上下文绑定东西的常用模式。
我高度拒绝这个原因有几个。首先:通常意味着你必须保留一个引用你的NavigationController来修正上下文泄漏,但是根本不解决这个架构。
最好的方式(在我的oppinion)是使用LiveData,它是生命周期感知,可以做所有想要的东西。
例子:
class YourVm : ViewModel() {
val uiEventLiveData = SingleLiveData<Pair<YourModel, Int>>()
fun onClick(item: YourModel) {
uiEventLiveData.value = item to 3 // can be predefined values
}
}
后,您可以在更改视图里面听。
class YourFragmentOrActivity {
//assign your vm whatever
override fun onActivityCreated(savedInstanceState: Bundle?) {
var context = this
yourVm.uiEventLiveData.observe(this, Observer {
when (it?.second) {
1 -> { context.startActivity(...) }
2 -> { .. }
}
})
}
}
请小心,香港专业教育学院使用修改MutableLiveData,因为否则它会一直发出新的观察员,这导致不良行为的最新结果。例如,如果您更改活动并返回,它将以循环结束。
class SingleLiveData<T> : MutableLiveData<T>() {
private val mPending = AtomicBoolean(false)
@MainThread
override fun observe(owner: LifecycleOwner, observer: Observer<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 val TAG = "SingleLiveData"
}
}
为什么是更好的尝试使用,然后在WeakReferences,接口,或任何其他解决方案?
因为此事件将UI逻辑与业务逻辑分开。它也可能有多个观察员。它关心生命周期。它没有泄漏任何东西。
您也可以通过使用PublishSubject使用RxJava代替LiveData来解决此问题。 (addTo
要求RxKotlin)
注意不要通过在onStop()中释放它来泄漏订阅。
class YourVm : ViewModel() {
var subject : PublishSubject<YourItem> = PublishSubject.create();
}
class YourFragmentOrActivityOrWhatever {
var composite = CompositeDisposable()
onStart() {
YourVm.subject
.subscribe({ Log.d("...", "Event emitted $it") }, { error("Error occured $it") })
.addTo(compositeDisposable)
}
onStop() {
compositeDisposable.clear()
}
}
还要注意将ViewModel绑定到Activity或片段。您不能在多个活动之间共享ViewModel,因为这会打破“Livecycle-Awareness”。
如果您需要使用像room这样的数据库来保存数据,或者使用parcel共享数据。
谢谢。很高兴帮助你:-) –