Skip to content

Instantly share code, notes, and snippets.

@ShinichiroFunatsu
Last active July 15, 2020 05:19
Show Gist options
  • Save ShinichiroFunatsu/5fe30c625c7ac6803083397c687bd7a4 to your computer and use it in GitHub Desktop.
Save ShinichiroFunatsu/5fe30c625c7ac6803083397c687bd7a4 to your computer and use it in GitHub Desktop.
IntelliJ File Template for Android App Development work.
package ${PACKAGE_NAME}
import androidx.annotation.MainThread
import androidx.lifecycle.*
import kotlinx.coroutines.coroutineScope
#parse("File Header.java")
class ${NAME} (
private val getFooUseCase: GetFooUseCase
) : ViewModel() {
// State of ViewModel
private class State(
val getFooResult: LiveData<GetFooResult>,
val selectedFoo: MutableLiveData<SelectedFoo> = MutableLiveData<SelectedFoo>(SelectedFoo.None)
) {
val isAnySelected: Boolean
get() = selectedFoo.value != SelectedFoo.None
val result: Result
get() = Result(getFooResult = getFooResult.value!!)
}
// Snapshot of State: customize parameter and add other results on demand.
data class Result(val getFooResult: GetFooResult)
private val _state = State(
getFooResult = liveData(context = viewModelScope.coroutineContext) {
val result = getFooUseCase.load()
emit(result)
}
)
private val _result: MutableLiveData<Result> = MutableLiveData()
val foo: LiveData<Foo>
get() = _state.getFooResult.filterIsInstance<GetFooResult.Success>()
.map { it.foo }
val foos: LiveData<List<Foo>>
get() = _state.getFooResult.filterIsInstance<GetFooResult.Success2>()
.map { it.foos }
val error: LiveData<Throwable>
get() = _state.getFooResult.filterIsInstance<GetFooResult.Error>()
.map { it.error }
val goToNext: LiveData<Result>
get() = _result
fun onClickNext() {
_result.value = _state.result
}
}
class GetFooUseCase() {
suspend fun load() = coroutineScope {
runCatching {
Foo()
}.fold(onSuccess = {
GetFooResult.Success(it)
}, onFailure = {
GetFooResult.Error(it)
})
}
}
sealed class GetFooResult {
// customize on demand
data class Success(val foo: Foo) : GetFooResult()
data class Success2(val foos: List<Foo>) : GetFooResult()
data class Error(val error: Throwable) : GetFooResult()
}
data class Foo(val id: String = "dummyId")
sealed class SelectedFoo {
object None: SelectedFoo()
// add on demand
}
// replace LiveData extension functions following if defined in other files.
@MainThread
@Suppress("UNCHECKED_CAST")
inline fun <reified R> LiveData<*>.filterIsInstance(): LiveData<R> = filter { it is R } as LiveData<R>
@MainThread
inline fun <X> LiveData<X>.filter(crossinline predicate: (X) -> Boolean): LiveData<X> = this.transform { x ->
if (predicate(x)) this.value = x
}
@MainThread
inline fun <X, Y> LiveData<X>.transform(
crossinline transform: MediatorLiveData<Y>.(value: X) -> Unit
): LiveData<Y> {
val result = MediatorLiveData<Y>()
result.addSource(
this
) { x ->
result.transform(x)
}
return result
}
@MainThread
@Suppress("UNCHECKED_CAST")
inline fun <reified R> LiveData<*>.filterIsInstance(): LiveData<R> = filter { it is R } as LiveData<R>
@MainThread
inline fun <X> LiveData<X>.filter(crossinline predicate: (X) -> Boolean): LiveData<X> = this.transform { x ->
if (predicate(x)) this.value = x
}
@MainThread
inline fun <X, Y> LiveData<X>.transform(
crossinline transform: MediatorLiveData<Y>.(value: X) -> Unit
): LiveData<Y> {
val result = MediatorLiveData<Y>()
result.addSource(
this
) { x ->
result.transform(x)
}
return result
}
@ShinichiroFunatsu
Copy link
Author

jp:
01ViewModelTemplate: 一つのファイルで完結できるようにしたものです。
02LiveDataEx.kt: こちらを別ファイルに定義した場合は重複を取り除いてください。

en:
01ViewModelTemplate: It can be completed with one file.
02LiveDataEx.kt: If you define this in another file, please remove the duplication.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment