From d9dcc1253f613bf1ba185ec731fe9ff1acfec3f1 Mon Sep 17 00:00:00 2001 From: CraZyLegenD Date: Fri, 13 Nov 2020 12:55:08 +0100 Subject: [PATCH] feat: state flow retrofit and db extensions --- .../MainAbstractActivity.kt | 79 +++--- .../setofusefulkotlinextensions/TestAVM.kt | 15 +- .../database/DBResultExtensions.kt | 61 ++++- .../coroutines/CoroutineDBCallsLiveData.kt | 16 +- .../coroutines/CoroutineDBCallsStateFlow.kt | 161 +++++++++++- .../retrofit/coroutines/CoroutineApiCalls.kt | 29 ++- .../coroutines/CoroutineApiCallsStateFlow.kt | 232 ++++++++++++++++++ .../RetrofitResultExtensions.kt | 34 ++- 8 files changed, 561 insertions(+), 66 deletions(-) create mode 100644 retrofit/src/main/java/com/crazylegend/retrofit/coroutines/CoroutineApiCallsStateFlow.kt diff --git a/app/src/main/java/com/crazylegend/setofusefulkotlinextensions/MainAbstractActivity.kt b/app/src/main/java/com/crazylegend/setofusefulkotlinextensions/MainAbstractActivity.kt index e02c69e03..1f1a0dcdd 100644 --- a/app/src/main/java/com/crazylegend/setofusefulkotlinextensions/MainAbstractActivity.kt +++ b/app/src/main/java/com/crazylegend/setofusefulkotlinextensions/MainAbstractActivity.kt @@ -6,13 +6,12 @@ import android.view.Menu import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.SearchView import androidx.core.os.bundleOf +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.RecyclerView import androidx.transition.Fade import androidx.transition.Transition import androidx.transition.TransitionListenerAdapter import androidx.transition.TransitionManager -import com.crazylegend.biometrics.biometricAuth -import com.crazylegend.biometrics.canAuthenticate import com.crazylegend.customviews.AppRater import com.crazylegend.customviews.autoStart.AutoStartHelper import com.crazylegend.customviews.autoStart.ConfirmationDialogAutoStart @@ -42,6 +41,8 @@ import com.crazylegend.setofusefulkotlinextensions.adapter.TestViewHolderShimmer import com.crazylegend.setofusefulkotlinextensions.databinding.ActivityMainBinding import com.crazylegend.viewbinding.viewBinding import io.reactivex.rxjava3.disposables.CompositeDisposable +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch import java.io.File class MainAbstractActivity : AppCompatActivity() { @@ -99,7 +100,8 @@ class MainAbstractActivity : AppCompatActivity() { debug("SECURITY isEmulator ${isEmulator()}") debug("SECURITY getShaSignature ${getShaSignature(BuildConfig.APPLICATION_ID)}") - canAuthenticate(hardwareUnavailable = { + + /*canAuthenticate(hardwareUnavailable = { //some message about hardware missing }, noFingerprintsEnrolled = { //make user action to enroll fingerprints @@ -118,10 +120,14 @@ class MainAbstractActivity : AppCompatActivity() { }) { //handle successful authentication } - } + }*/ activityMainBinding.test.setOnClickListener { - testAVM.getposts() + lifecycleScope.launch { + testAVM.getposts().collect { + updateUI(it) + } + } } RunCodeEveryXLaunchOnAppOpened.runCode(this, 2) { @@ -170,39 +176,12 @@ class MainAbstractActivity : AppCompatActivity() { EdgeToEdge.setUpScrollingContent(activityMainBinding.recycler) } - val stagger = StaggerTransition() - - testAVM.posts.observe(this, { - it?.apply { - when (it) { - is RetrofitResult.Success -> { - TransitionManager.beginDelayedTransition(activityMainBinding.recycler, stagger) - if (activityMainBinding.recycler.adapter != generatedAdapter) { - activityMainBinding.recycler.adapter = generatedAdapter - savedItemAnimator = activityMainBinding.recycler.itemAnimator - activityMainBinding.recycler.itemAnimator = null - TransitionManager.beginDelayedTransition(activityMainBinding.recycler, fade) - } - generatedAdapter.submitList(it.value) - val wrappedList = it.value.toMutableList() - activityMainBinding.recycler.addDrag(generatedAdapter, wrappedList) - } - RetrofitResult.Loading -> { - activityMainBinding.recycler.adapter = testPlaceHolderAdapter - } - RetrofitResult.EmptyData -> { - } - is RetrofitResult.Error -> { - } - is RetrofitResult.ApiError -> { - } - }.exhaustive + lifecycleScope.launchWhenResumed { + testAVM.apiTestState.collect { + updateUI(it) } - }) + } - testAVM.filteredPosts.observe(this, { - generatedAdapter.submitList(it) - }) val testFile = File(filesDir, "testfile.txt") encryptFileSafely(testFile, fileContent = "JETPACK SECURITY".toByteArray()) @@ -211,6 +190,34 @@ class MainAbstractActivity : AppCompatActivity() { debug("TEXT ENCRYPTED ${testFile.readText()}") } + private fun updateUI(retrofitResult: RetrofitResult>) { + val stagger = StaggerTransition() + + when (retrofitResult) { + is RetrofitResult.Success -> { + TransitionManager.beginDelayedTransition(activityMainBinding.recycler, stagger) + if (activityMainBinding.recycler.adapter != generatedAdapter) { + activityMainBinding.recycler.adapter = generatedAdapter + savedItemAnimator = activityMainBinding.recycler.itemAnimator + activityMainBinding.recycler.itemAnimator = null + TransitionManager.beginDelayedTransition(activityMainBinding.recycler, fade) + } + generatedAdapter.submitList(retrofitResult.value) + val wrappedList = retrofitResult.value.toMutableList() + activityMainBinding.recycler.addDrag(generatedAdapter, wrappedList) + } + RetrofitResult.Loading -> { + activityMainBinding.recycler.adapter = testPlaceHolderAdapter + } + RetrofitResult.EmptyData -> { + } + is RetrofitResult.Error -> { + } + is RetrofitResult.ApiError -> { + } + }.exhaustive + } + private var searchView: SearchView? = null override fun onCreateOptionsMenu(menu: Menu?): Boolean { diff --git a/app/src/main/java/com/crazylegend/setofusefulkotlinextensions/TestAVM.kt b/app/src/main/java/com/crazylegend/setofusefulkotlinextensions/TestAVM.kt index 6b2adf901..595570059 100644 --- a/app/src/main/java/com/crazylegend/setofusefulkotlinextensions/TestAVM.kt +++ b/app/src/main/java/com/crazylegend/setofusefulkotlinextensions/TestAVM.kt @@ -1,12 +1,9 @@ package com.crazylegend.setofusefulkotlinextensions import android.app.Application -import androidx.lifecycle.AndroidViewModel -import androidx.lifecycle.LiveData -import androidx.lifecycle.MediatorLiveData -import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.* import com.crazylegend.retrofit.RetrofitClient -import com.crazylegend.retrofit.coroutines.makeApiCallLiveData +import com.crazylegend.retrofit.coroutines.apiCallStateFlow import com.crazylegend.retrofit.retrofitResult.RetrofitResult import com.crazylegend.retrofit.retrofitResult.getSuccess import com.crazylegend.rx.clearAndDispose @@ -33,10 +30,10 @@ class TestAVM(application: Application, testModel: TestModel, key: Int, string: private val compositeDisposable = CompositeDisposable() - fun getposts() { + //val apiTest = apiCallAsFlow { retrofit.getPosts() } + val apiTestState = getposts() - makeApiCallLiveData(postsData) { retrofit.getPosts() } - } + fun getposts() = viewModelScope.apiCallStateFlow { retrofit.getPosts() } fun filterBy(query: String) { filteredPostsData.value = postsData.getSuccess?.filter { @@ -55,7 +52,7 @@ class TestAVM(application: Application, testModel: TestModel, key: Int, string: } init { - getposts() + // getposts() } } diff --git a/database/src/main/java/com/crazylegend/database/DBResultExtensions.kt b/database/src/main/java/com/crazylegend/database/DBResultExtensions.kt index 2dc9336f6..1143fd513 100644 --- a/database/src/main/java/com/crazylegend/database/DBResultExtensions.kt +++ b/database/src/main/java/com/crazylegend/database/DBResultExtensions.kt @@ -2,6 +2,7 @@ package com.crazylegend.database import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import kotlinx.coroutines.flow.MutableStateFlow /** @@ -224,4 +225,62 @@ inline val LiveData>.getSuccess: T? } internal inline fun T.isListAndNotNullOrEmpty(actionFalse: () -> R, actionTrue: () -> R): R = - if (this is List<*> && !this.isNullOrEmpty()) actionTrue() else actionFalse() \ No newline at end of file + if (this is List<*> && !this.isNullOrEmpty()) actionTrue() else actionFalse() + + +fun MutableStateFlow>.querying() { + value = databaseQuerying +} + + +fun MutableStateFlow>.emptyData() { + value = databaseEmptyDB +} + + +fun MutableStateFlow>.subscribe(queryModel: T?, includeEmptyData: Boolean = false) { + if (includeEmptyData) { + if (queryModel == null) { + value = databaseEmptyDB + } else { + value = databaseSuccess(queryModel) + } + } else { + queryModel?.apply { + value = databaseSuccess(this) + } + } +} + + +fun MutableStateFlow>.subscribeList(queryModel: T?, includeEmptyData: Boolean = false) { + if (includeEmptyData) { + if (queryModel == null) { + value = databaseEmptyDB + } else { + if (this is List<*>) { + val list = this as List<*> + if (list.isNullOrEmpty()) { + value = databaseEmptyDB + } else { + value = databaseSuccess(queryModel) + } + } else { + value = databaseSuccess(queryModel) + } + } + } else { + queryModel?.apply { + value = databaseSuccess(this) + } + } +} + + +fun MutableStateFlow>.callError(throwable: Throwable) { + value = databaseError(throwable) +} + +fun MutableStateFlow>.success(model: T) { + value = databaseSuccess(model) +} \ No newline at end of file diff --git a/database/src/main/java/com/crazylegend/database/coroutines/CoroutineDBCallsLiveData.kt b/database/src/main/java/com/crazylegend/database/coroutines/CoroutineDBCallsLiveData.kt index 0cdff2b56..77d0ccaf0 100644 --- a/database/src/main/java/com/crazylegend/database/coroutines/CoroutineDBCallsLiveData.kt +++ b/database/src/main/java/com/crazylegend/database/coroutines/CoroutineDBCallsLiveData.kt @@ -6,6 +6,8 @@ import com.crazylegend.database.* import kotlinx.coroutines.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.onStart import kotlin.coroutines.CoroutineContext @@ -225,7 +227,7 @@ inline fun CoroutineScope.makeDBCallListAsync( } -inline fun AndroidViewModel.makeDBCallListAsync( +inline fun ViewModel.makeDBCallListAsync( dbResult: MutableLiveData>, includeEmptyData: Boolean = true, crossinline dbCall: suspend () -> T?): Job { @@ -245,7 +247,7 @@ inline fun AndroidViewModel.makeDBCallListAsync( } -inline fun AndroidViewModel.makeDBCallAsync( +inline fun ViewModel.makeDBCallAsync( dbResult: MutableLiveData>, includeEmptyData: Boolean = false, crossinline dbCall: suspend () -> T?): Job { @@ -601,3 +603,13 @@ fun CoroutineScope.makeDBCallFlow( } } +fun dbCallAsFlow(apiCall: suspend () -> T?): Flow> = + flow { + try { + emit(databaseSubscribe(apiCall.invoke())) + } catch (t: Throwable) { + emit(databaseError(t)) + } + }.onStart { + emit(databaseQuerying) + } \ No newline at end of file diff --git a/database/src/main/java/com/crazylegend/database/coroutines/CoroutineDBCallsStateFlow.kt b/database/src/main/java/com/crazylegend/database/coroutines/CoroutineDBCallsStateFlow.kt index bc53105b8..22d31b0ff 100644 --- a/database/src/main/java/com/crazylegend/database/coroutines/CoroutineDBCallsStateFlow.kt +++ b/database/src/main/java/com/crazylegend/database/coroutines/CoroutineDBCallsStateFlow.kt @@ -3,15 +3,11 @@ package com.crazylegend.database.coroutines import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.crazylegend.coroutines.ioDispatcher -import com.crazylegend.database.DBResult -import com.crazylegend.database.databaseError -import com.crazylegend.database.databaseSubscribe -import com.crazylegend.database.databaseSubscribeList -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.async -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.launch -import kotlinx.coroutines.supervisorScope +import com.crazylegend.coroutines.mainDispatcher +import com.crazylegend.coroutines.viewModelIOCoroutine +import com.crazylegend.database.* +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* /** * Created by crazy on 11/10/20 to long live and prosper ! @@ -86,3 +82,150 @@ inline fun > CoroutineScope.makeDBCallListStateFlow(stateFlow: M } } } + + +fun CoroutineScope.apiCallStateFlow(sharing: SharingStarted = SharingStarted.WhileSubscribed(), + initialValue: DBResult = databaseQuerying, + apiCall: suspend () -> T?): StateFlow> = + flow { + try { + emit(databaseSubscribe(apiCall.invoke())) + } catch (t: Throwable) { + emit(databaseError(t)) + } + }.onStart { + emit(databaseQuerying) + }.stateIn(this, sharing, initialValue) + + +suspend fun CoroutineScope.apiCallStateFlowInScope(apiCall: suspend () -> T?): StateFlow> = + flow { + try { + emit(databaseSubscribe(apiCall.invoke())) + } catch (t: Throwable) { + emit(databaseError(t)) + } + }.onStart { + emit(databaseQuerying) + }.stateIn(this) + + +suspend fun apiCallStateFlowWithinScope(coroutineScope: CoroutineScope, apiCall: suspend () -> T?): StateFlow> = + flow { + try { + emit(databaseSubscribe(apiCall.invoke())) + } catch (t: Throwable) { + emit(databaseError(t)) + } + }.onStart { + emit(databaseQuerying) + }.stateIn(coroutineScope) + + +fun CoroutineScope.makeApiCallList( + dbResult: MutableStateFlow>, + includeEmptyData: Boolean = true, + apiCall: suspend () -> T?): Job { + + dbResult.querying() + + return launch(ioDispatcher) { + try { + dbResult.subscribeList(apiCall(), includeEmptyData) + } catch (t: Throwable) { + dbResult.callError(t) + } + } +} + +fun CoroutineScope.makeApiCall( + dbResult: MutableStateFlow>, + apiCall: suspend () -> T?): Job { + dbResult.querying() + return launch(ioDispatcher) { + try { + dbResult.subscribe(apiCall()) + } catch (t: Throwable) { + dbResult.callError(t) + } + } +} + + +fun CoroutineScope.makeApiCallList( + response: T?, + dbResult: MutableStateFlow>, + includeEmptyData: Boolean = true +): Job { + dbResult.querying() + return launch(ioDispatcher) { + try { + dbResult.subscribeList(response, includeEmptyData) + } catch (t: Throwable) { + dbResult.callError(t) + } + } + +} + +fun ViewModel.makeApiCallList( + dbResult: MutableStateFlow>, + includeEmptyData: Boolean = true, + apiCall: suspend () -> T?): Job { + dbResult.querying() + return viewModelIOCoroutine { + try { + dbResult.subscribeList(apiCall(), includeEmptyData) + } catch (t: Throwable) { + dbResult.callError(t) + } + } +} + +fun CoroutineScope.makeApiCall( + response: T?, + dbResult: MutableStateFlow> +): Job { + dbResult.querying() + return launch(ioDispatcher) { + try { + dbResult.subscribe(response) + } catch (t: Throwable) { + dbResult.callError(t) + } + } + +} + +fun ViewModel.makeApiCall( + dbResult: MutableStateFlow>, + apiCall: suspend () -> T?): Job { + dbResult.querying() + return viewModelIOCoroutine { + try { + dbResult.subscribe(apiCall()) + } catch (t: Throwable) { + dbResult.callError(t) + } + } +} + + +fun CoroutineScope.makeApiCallAsync( + dbResult: MutableStateFlow>, + apiCall: suspend () -> T?): Job { + + return launch(mainDispatcher) { + supervisorScope { + dbResult.querying() + try { + val task = async(ioDispatcher) { + apiCall() + } + dbResult.subscribe(task.await()) + } catch (t: Throwable) { + dbResult.callError(t) + } + } + } +} \ No newline at end of file diff --git a/retrofit/src/main/java/com/crazylegend/retrofit/coroutines/CoroutineApiCalls.kt b/retrofit/src/main/java/com/crazylegend/retrofit/coroutines/CoroutineApiCalls.kt index 87824ceb3..6423f20ce 100644 --- a/retrofit/src/main/java/com/crazylegend/retrofit/coroutines/CoroutineApiCalls.kt +++ b/retrofit/src/main/java/com/crazylegend/retrofit/coroutines/CoroutineApiCalls.kt @@ -4,6 +4,9 @@ import androidx.lifecycle.* import com.crazylegend.coroutines.* import com.crazylegend.retrofit.retrofitResult.* import kotlinx.coroutines.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.onStart import okhttp3.ResponseBody import retrofit2.Response import kotlin.coroutines.CoroutineContext @@ -238,7 +241,7 @@ suspend fun LiveDataScope>.subscribeApiCallList(res: Respo } } -fun AndroidViewModel.makeApiCallListAsync( +fun ViewModel.makeApiCallListAsync( retrofitResult: MutableLiveData>, includeEmptyData: Boolean = true, apiCall: suspend () -> Response?): Job { @@ -257,7 +260,7 @@ fun AndroidViewModel.makeApiCallListAsync( } } -fun AndroidViewModel.makeApiCallAsync( +fun ViewModel.makeApiCallAsync( retrofitResult: MutableLiveData>, apiCall: suspend () -> Response?): Job { @@ -489,10 +492,10 @@ fun CoroutineContext.makeApiCallListLiveData(mediatorLiveData: MediatorLiveD } -fun AndroidViewModel.makeApiCallAsync(apiCall: suspend () -> Response?, - onError: (throwable: Throwable) -> Unit = { _ -> }, - onUnsuccessfulCall: (errorBody: ResponseBody?, responseCode: Int) -> Unit = { _, _ -> }, - onResponse: (response: T?) -> Unit +fun ViewModel.makeApiCallAsync(apiCall: suspend () -> Response?, + onError: (throwable: Throwable) -> Unit = { _ -> }, + onUnsuccessfulCall: (errorBody: ResponseBody?, responseCode: Int) -> Unit = { _, _ -> }, + onResponse: (response: T?) -> Unit ): Job { return viewModelScope.launch(mainDispatcher) { @@ -551,7 +554,6 @@ fun CoroutineScope.makeApiCallAsync( retrofitResult: MutableLiveData>, apiCall: suspend () -> Response?): Job { - return launch(mainDispatcher) { supervisorScope { retrofitResult.loading() @@ -756,4 +758,15 @@ fun CoroutineScope.makeApiCallList( } } -} \ No newline at end of file +} + +fun apiCallAsFlow(apiCall: suspend () -> Response?): Flow> = + flow { + try { + emit(retrofitSubscribe(apiCall.invoke())) + } catch (t: Throwable) { + emit(retrofitCallError(t)) + } + }.onStart { + emit(retrofitLoading) + } diff --git a/retrofit/src/main/java/com/crazylegend/retrofit/coroutines/CoroutineApiCallsStateFlow.kt b/retrofit/src/main/java/com/crazylegend/retrofit/coroutines/CoroutineApiCallsStateFlow.kt new file mode 100644 index 000000000..d521bf1b3 --- /dev/null +++ b/retrofit/src/main/java/com/crazylegend/retrofit/coroutines/CoroutineApiCallsStateFlow.kt @@ -0,0 +1,232 @@ +package com.crazylegend.retrofit.coroutines + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.crazylegend.coroutines.ioDispatcher +import com.crazylegend.coroutines.mainDispatcher +import com.crazylegend.coroutines.viewModelIOCoroutine +import com.crazylegend.retrofit.retrofitResult.* +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import retrofit2.Response + +/** + * Created by crazy on 11/12/20 to long live and prosper ! + */ + + +fun CoroutineScope.apiCallStateFlow(sharing: SharingStarted = SharingStarted.WhileSubscribed(), + initialValue: RetrofitResult = RetrofitResult.Loading, + apiCall: suspend () -> Response?): StateFlow> = + flow { + try { + emit(retrofitSubscribe(apiCall.invoke())) + } catch (t: Throwable) { + emit(RetrofitResult.Error(t)) + } + }.onStart { + emit(RetrofitResult.Loading) + }.stateIn(this, sharing, initialValue) + + +suspend fun CoroutineScope.apiCallStateFlowInScope(apiCall: suspend () -> Response?): StateFlow> = + flow { + try { + emit(retrofitSubscribe(apiCall.invoke())) + } catch (t: Throwable) { + emit(RetrofitResult.Error(t)) + } + }.onStart { + emit(RetrofitResult.Loading) + }.stateIn(this) + + +suspend fun apiCallStateFlowWithinScope(coroutineScope: CoroutineScope, apiCall: suspend () -> Response?): StateFlow> = + flow { + try { + emit(retrofitSubscribe(apiCall.invoke())) + } catch (t: Throwable) { + emit(RetrofitResult.Error(t)) + } + }.onStart { + emit(RetrofitResult.Loading) + }.stateIn(coroutineScope) + + +fun CoroutineScope.makeApiCallList( + retrofitResult: MutableStateFlow>, + includeEmptyData: Boolean = true, + apiCall: suspend () -> Response?): Job { + + retrofitResult.loading() + + return launch(ioDispatcher) { + try { + retrofitResult.subscribeList(apiCall(), includeEmptyData) + } catch (t: Throwable) { + retrofitResult.callError(t) + } + } +} + +fun CoroutineScope.makeApiCall( + retrofitResult: MutableStateFlow>, + apiCall: suspend () -> Response?): Job { + retrofitResult.loading() + return launch(ioDispatcher) { + try { + retrofitResult.subscribe(apiCall()) + } catch (t: Throwable) { + retrofitResult.callError(t) + } + } +} + + +fun CoroutineScope.makeApiCallList( + response: Response?, + retrofitResult: MutableStateFlow>, + includeEmptyData: Boolean = true +): Job { + retrofitResult.loading() + return launch(ioDispatcher) { + try { + retrofitResult.subscribeList(response, includeEmptyData) + } catch (t: Throwable) { + retrofitResult.callError(t) + } + } + +} + +fun ViewModel.makeApiCallList( + retrofitResult: MutableStateFlow>, + includeEmptyData: Boolean = true, + apiCall: suspend () -> Response?): Job { + retrofitResult.loading() + return viewModelIOCoroutine { + try { + retrofitResult.subscribeList(apiCall(), includeEmptyData) + } catch (t: Throwable) { + retrofitResult.callError(t) + } + } +} + +fun CoroutineScope.makeApiCall( + response: Response?, + retrofitResult: MutableStateFlow> +): Job { + retrofitResult.loading() + return launch(ioDispatcher) { + try { + retrofitResult.subscribe(response) + } catch (t: Throwable) { + retrofitResult.callError(t) + } + } + +} + +fun ViewModel.makeApiCall( + retrofitResult: MutableStateFlow>, + apiCall: suspend () -> Response?): Job { + retrofitResult.loading() + return viewModelIOCoroutine { + try { + retrofitResult.subscribe(apiCall()) + } catch (t: Throwable) { + retrofitResult.callError(t) + } + } +} + + +fun CoroutineScope.makeApiCallAsync( + retrofitResult: MutableStateFlow>, + apiCall: suspend () -> Response?): Job { + + return launch(mainDispatcher) { + supervisorScope { + retrofitResult.loading() + try { + val task = async(ioDispatcher) { + apiCall() + } + retrofitResult.subscribe(task.await()) + } catch (t: Throwable) { + retrofitResult.callError(t) + } + } + } +} + +inline fun > ViewModel.makeDBCallStateFlow(stateFlow: MutableStateFlow>, crossinline dbCall: suspend () -> Response?) { + viewModelScope.launch { + supervisorScope { + stateFlow.value = retrofitLoading + try { + val task = async(ioDispatcher) { + dbCall() + } + stateFlow.value = retrofitSubscribe(task.await()) + } catch (t: Throwable) { + stateFlow.value = retrofitCallError(t) + } + } + } +} + +inline fun > ViewModel.makeDBCallListStateFlow(stateFlow: MutableStateFlow>, + includeEmptyData: Boolean = false, + crossinline dbCall: suspend () -> Response?) { + viewModelScope.launch { + supervisorScope { + stateFlow.value = retrofitLoading + try { + val task = async(ioDispatcher) { + dbCall() + } + stateFlow.value = retrofitSubscribeList(task.await(), includeEmptyData) + } catch (t: Throwable) { + stateFlow.value = retrofitCallError(t) + } + } + } +} + +inline fun > CoroutineScope.makeDBCallStateFlow(stateFlow: MutableStateFlow>, crossinline dbCall: suspend () -> Response?) { + + launch { + supervisorScope { + stateFlow.value = retrofitLoading + + try { + val task = async(ioDispatcher) { + dbCall() + } + stateFlow.value = retrofitSubscribe(task.await()) + } catch (t: Throwable) { + stateFlow.value = retrofitCallError(t) + } + } + } +} + +inline fun > CoroutineScope.makeDBCallListStateFlow(stateFlow: MutableStateFlow>, + includeEmptyData: Boolean = false, + crossinline dbCall: suspend () -> Response?) { + launch { + supervisorScope { + stateFlow.value = retrofitLoading + try { + val task = async(ioDispatcher) { + dbCall() + } + stateFlow.value = retrofitSubscribeList(task.await(), includeEmptyData) + } catch (t: Throwable) { + stateFlow.value = retrofitCallError(t) + } + } + } +} diff --git a/retrofit/src/main/java/com/crazylegend/retrofit/retrofitResult/RetrofitResultExtensions.kt b/retrofit/src/main/java/com/crazylegend/retrofit/retrofitResult/RetrofitResultExtensions.kt index 6e41d4195..c4f085707 100644 --- a/retrofit/src/main/java/com/crazylegend/retrofit/retrofitResult/RetrofitResultExtensions.kt +++ b/retrofit/src/main/java/com/crazylegend/retrofit/retrofitResult/RetrofitResultExtensions.kt @@ -3,6 +3,7 @@ package com.crazylegend.retrofit.retrofitResult import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.crazylegend.retrofit.errorResponseCodeMessage +import kotlinx.coroutines.flow.MutableStateFlow import okhttp3.ResponseBody import retrofit2.Response @@ -356,4 +357,35 @@ fun RetrofitResult.onSuccess(function: (model: T) -> Unit = { _ -> }) { //endregion internal inline fun T.isListAndNotNullOrEmpty(actionFalse: () -> R, actionTrue: () -> R): R = - if (this is List<*> && !this.isNullOrEmpty()) actionTrue() else actionFalse() \ No newline at end of file + if (this is List<*> && !this.isNullOrEmpty()) actionTrue() else actionFalse() + + +fun MutableStateFlow>.loading() { + value = retrofitLoading +} + + +fun MutableStateFlow>.emptyData() { + value = retrofitEmptyData +} + +fun MutableStateFlow>.subscribe(response: Response?) { + value = retrofitSubscribe(response) +} + +fun MutableStateFlow>.subscribeList(response: Response?, includeEmptyData: Boolean = false) { + value = retrofitSubscribeList(response, includeEmptyData) +} + +fun MutableStateFlow>.callError(throwable: Throwable) { + value = retrofitCallError(throwable) +} + + +fun MutableStateFlow>.success(model: T) { + value = retrofitSuccess(model) +} + +fun MutableStateFlow>.apiError(code: Int, errorBody: ResponseBody?) { + value = retrofitApiError(code, errorBody) +} \ No newline at end of file