Xavier Lian
10/04/2019, 1:56 AMclass MyVM(
private val vmDidSummonLoadingScreen: () -> Unit,
private val vmDidDismissLoadingScreen: () -> Unit
)
{
fun doAFlip()
{
vmDidSummonLoadingScreen()
startSuperLongAsyncTask {
vmDidDismissLoadingScreen()
}
}
}
Here’s some example UI in Android
class FMMain: Fragment()
{
val loadingScreenVw: View get() = fm_main_vw_loading_screen //From XML
val vm: MyVM by lazy { //Problem a1
MyVM(
vmDidSummonLoadingScreen = { //Problem a0
loadingScreenVw.visibility = View.VISIBLE
},
vmDidDismissLoadingScreen = { //Problem a0
loadingScreenVw.visibility = View.GONE
}
)
}
override fun onCreate(...)
{
super.onCreate(...)
vm.doAFlip()
}
}
Problems:
a0: The lambdas will leak the instance of FMMain since the lambdas reference a property of FMMain thereby implicitly capturing it.
a1: Assuming the lambdas don’t leak, when the device rotates, the UI dies and so does the VM. There is the Android Component Library ViewModel class that solves this, but that can’t be used in the shared module.
iOS is excluded because this architecture works pretty well since Swift has [weak self] to prevent strong captures.
So my questions are:
1: How does one release lambda captures?
1.1: If not possible, what is the best way to let the UI layer know that an event happened in the VM without using any external libs/dependencies (just idomatic kotlin)?
2: Only in Android, I am considering wrapping my VM with an object that inherits from Android’s Architecture Components’ ViewModel (possibly generic idk if I can do that yet). Is there a better alternative in your opinion?
3. In your opinion, should VMs be injected into Fragments, or should Fragments instantiate and own their own VMs?alex009
10/04/2019, 2:26 AMXavier Lian
10/04/2019, 5:31 PMNeil
10/05/2019, 3:53 PMXavier Lian
10/08/2019, 6:05 AMclass AVMThingy(private val sharedVM: VMThingy)
{
val vmDidSetLoadingIndicator: LiveData<Boolean>
get() = _vmDidSetLoadingIndicator
private val _vmDidSetLoadingIndicator: = MutableLiveData<Boolean>()
init
{
sharedVM.vmDidSetLoadingIndicator = { active ->
//This implicitly captures this VM which is fine since it's not volatile like AndroidUI, right?
this._vmDidSetLoadingIndicator = active
}
}
}