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共享數據。
謝謝。很高興幫助你:-) –