Skip to content

Instantly share code, notes, and snippets.

@tuannha95
Created October 28, 2020 07:42
Show Gist options
  • Select an option

  • Save tuannha95/76df199323e441923a5b14deb0b86bcb to your computer and use it in GitHub Desktop.

Select an option

Save tuannha95/76df199323e441923a5b14deb0b86bcb to your computer and use it in GitHub Desktop.

Revisions

  1. tuannha95 created this gist Oct 28, 2020.
    100 changes: 100 additions & 0 deletions BaseViewModel.kt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,100 @@
    package com.gunaya.demo.demomeow.presentation.base

    import androidx.lifecycle.MediatorLiveData
    import androidx.lifecycle.MutableLiveData
    import androidx.lifecycle.ViewModel
    import com.gunaya.demo.demomeow.utils.EventWrapper
    import com.gunaya.demo.demomeow.utils.SingleLiveEvent
    import com.gunaya.demo.demomeow.utils.UseCaseResult
    import kotlinx.coroutines.*
    import kotlin.coroutines.CoroutineContext

    // To avoid writing the same extensions multiple times, we'll make an abstract class for ViewModels
    abstract class BaseViewModel : ViewModel(), CoroutineScope {

    // Coroutine's background job
    private val job = Job()

    // Define default thread for Coroutine as Main and add job
    override val coroutineContext: CoroutineContext = job + Dispatchers.Main

    val loading = MutableLiveData<EventWrapper<Boolean>>()
    val error = SingleLiveEvent<String>()

    val isLoading = MutableLiveData<Boolean>().apply { value = false }

    private val isShowLoading = MutableLiveData<Boolean>().apply {
    value = false
    }

    val isShowDialogLoading = MediatorLiveData<Boolean>().apply {
    value = false
    addSource(isLoading) {
    value = it && isShowLoading.value == true
    }
    addSource(isShowLoading) {
    value = isLoading.value == true && it
    }
    }

    open suspend fun onError(throwable: Throwable) {
    withContext(Dispatchers.Main) {
    hideLoading()
    }
    }

    open fun showError(e: Throwable) {
    error.value = e.message
    }

    fun showLoading() {
    isLoading.value = true
    }

    fun hideLoading() {
    isLoading.value = false
    }

    fun showDialogLoading(isShow: Boolean) {
    showLoading()
    isShowLoading.value = isShow
    }

    fun hideDialogLoading(isShow: Boolean) {
    hideLoading()
    isShowLoading.value = isShow
    }

    fun handleError(result: UseCaseResult.DataError<*>) {
    error.value = result.data?.error?.errorDescription
    error.value = null
    }

    suspend inline fun <reified T : Any> callAPI(
    noinline result: suspend () -> UseCaseResult<T>,
    isShowDialogLoading: Boolean = true,
    crossinline handleSuccess: (T) -> Unit = {}
    ): T? {
    return coroutineScope {
    var data: T? = null
    try {
    showDialogLoading(isShowDialogLoading)
    when (val response = result.invoke()) {
    is UseCaseResult.Success<*> -> {
    data = response.data as T
    handleSuccess(data)
    }
    is UseCaseResult.DataError<*> -> {
    handleError(response)
    data = null
    }
    }
    hideDialogLoading(isShowDialogLoading)
    } catch (e: Exception) {
    e.printStackTrace()
    onError(e)
    }
    data
    }
    }
    }