Last active
August 17, 2019 05:48
-
-
Save kevivforever/1264571ff31e591a8c71011404e1f524 to your computer and use it in GitHub Desktop.
View Models
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class DoubleLiveData<A, B>(a: LiveData<A>, b: LiveData<B>) : MediatorLiveData<Pair<A?, B?>>() { | |
init { | |
addSource(a) { value = it to b.value } | |
addSource(b) { value = a.value to it } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open class Event<out T>(private val content: T) { | |
private var hasBeenHandled = AtomicBoolean(false) | |
/** | |
* Returns the content and prevents its use again. | |
*/ | |
fun getIfNotHandled(): T? = if (hasBeenHandled.getAndSet(true)) null else content | |
/** | |
* Returns the content, even if it's already been handled. | |
*/ | |
fun peek(): T = content | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Resource<out T> private constructor(val status: Status, val data: T?) { | |
companion object { | |
fun <T> success(data: T? = null): Resource<T> = Resource(Status.SUCCESS, data) | |
fun <T> error(data: T? = null): Resource<T> = Resource(Status.ERROR, data) | |
fun <T> loading(data: T? = null): Resource<T> = Resource(Status.LOADING, data) | |
fun <T> unknown(data: T? = null): Resource<T> = Resource(Status.UNKNOWN, data) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// if you have two different data sources and want to see if both the request are complete | |
private val isUserDataFetched: LiveData<Boolean> = | |
Transformations.map(userLiveData) { it.status == Status.SUCCESS } | |
private val isPostDataFetched: LiveData<Boolean> = | |
Transformations.map(postLiveData) { it.status == Status.SUCCESS } | |
val isDataFetchComplete: LiveData<Boolean> = Transformations.map(DoubleLiveData(isUserDataFetched, isPostDataFetched)) { | |
it.first == it.second && it.first!! && it.second!! | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class TripleLiveData<A, B, C>(first: LiveData<A>, second: LiveData<B>, third: LiveData<C>) : MediatorLiveData<Triple<A?, B?, C?>>() { | |
init { | |
addSource(first) { value = Triple(it, second.value, third.value) } | |
addSource(second) { value = Triple(first.value, it, third.value) } | |
addSource(third) { value = Triple(first.value, second.value, it) } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* When ViewModel require parameters in the constructor then ViewModelProviders.of(activity).get(ViewModel.class) do not work | |
* In this case we need to provide our own ViewModelProvider's Factory. | |
* create method is called by Android Framework when it needs to create a ViewModel instance. | |
* NOTE: When activity rotates then create method is not called but earlier instance of ViewModel is returned. | |
* that is why creator is provided here so that Android Framework can create the ViewModel instance according to its need. | |
* @T: It says that the ViewModelProviderFactory works with variable of type SplashViewModel | |
* Example: T -> SplashViewModel, | |
* | |
*/ | |
@Singleton | |
class ViewModelProviderFactory<T : ViewModel>( | |
private val kClass: KClass<T>, // KClass is the holder of class of type ViewModel that needs to be inject | |
private val creator: () -> T // This is the Lambda function, this is provided be the ActivityModule/FragmentModule, | |
// when creator lambda is called then that module creates and return the instance of ViewModel | |
) : ViewModelProvider.NewInstanceFactory() { | |
@Suppress("UNCHECKED_CAST") | |
@Throws(IllegalArgumentException::class) | |
override fun <T : ViewModel> create(modelClass: Class<T>): T { | |
if (modelClass.isAssignableFrom(kClass.java)) return creator() as T | |
throw IllegalArgumentException("Unknown class name") | |
} | |
} | |
create new viewmodel using above viewmodelfactory | |
ViewModelProviders.of(activity , ViewModelProviderFactory(MainViewModel::class) { | |
MainViewModel(userPreferences, databaseService, compositeDisposable) | |
}).get(MainViewModel::class.java) | |
/** | |
* Step 1 create viewmdel without any parameters | |
*/ | |
val vm: UserViewModel by lazy { ViewModelProviders.of(this).get(UserViewModel::class.java) } | |
/** | |
* Step 2 create viewmodel specific factory method to pass paramters | |
*/ | |
class UserViewModelFactory(val userId: Int) : ViewModelProvider.Factory { | |
override fun <T : ViewModel?> create(modelClass: Class<T>): T { | |
return UserViewModel(userId) as T | |
} | |
} | |
val vm: UserViewModel by lazy { | |
ViewModelProviders.of(this, UserViewModelFactory(intent.getIntExtra(USER_ID, -1))).get(UserViewModel::class.java) | |
} | |
/** | |
* Step 3 create base factory method so that we dont have create separate factory method for each viewmodel | |
*/ | |
class BaseViewModelFactory<T>(val creator: () -> T) : ViewModelProvider.Factory { | |
override fun <T : ViewModel?> create(modelClass: Class<T>): T { | |
return creator() as T | |
} | |
} | |
val vm: UserViewModel by lazy { | |
ViewModelProviders.of(this, BaseViewModelFactory { UserViewModel(intent.getIntExtra(USER_ID, -1)) }).get(UserViewModel::class.java) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment