From ec9a256d460d87053131a366737ef64735050bc6 Mon Sep 17 00:00:00 2001 From: Pratyush Singh Date: Sat, 4 Nov 2023 11:18:47 +0530 Subject: [PATCH] refactor #2415: client charge repository migrated to stateflow --- .../java/org/mifos/mobile/api/DataManager.kt | 10 +-- .../mifos/mobile/api/local/DatabaseHelper.kt | 12 ++-- .../api/services/ClientChargeService.kt | 6 +- .../repositories/ClientChargeRepository.kt | 10 +-- .../repositories/ClientChargeRepositoryImp.kt | 26 +++++--- .../ui/fragments/ClientChargeFragment.kt | 45 +++++++++----- .../mifos/mobile/utils/ClientChargeUiState.kt | 1 + .../viewModels/ClientChargeViewModel.kt | 62 ++++++------------- 8 files changed, 86 insertions(+), 86 deletions(-) diff --git a/app/src/main/java/org/mifos/mobile/api/DataManager.kt b/app/src/main/java/org/mifos/mobile/api/DataManager.kt index 301b01220..fdecaf09f 100644 --- a/app/src/main/java/org/mifos/mobile/api/DataManager.kt +++ b/app/src/main/java/org/mifos/mobile/api/DataManager.kt @@ -78,17 +78,17 @@ class DataManager @Inject constructor( .getRecentTransactionsList(clientId, offset, limit) } - suspend fun getClientCharges(clientId: Long): Response?>? { + suspend fun getClientCharges(clientId: Long): Page { return baseApiManager.clientChargeApi.getClientChargeList(clientId).apply { - databaseHelper.syncCharges(this?.body()) + databaseHelper.syncCharges(this) } } - suspend fun getLoanCharges(loanId: Long): Response?>? { + suspend fun getLoanCharges(loanId: Long): List { return baseApiManager.clientChargeApi.getLoanAccountChargeList(loanId) } - suspend fun getSavingsCharges(savingsId: Long): Response?>? { + suspend fun getSavingsCharges(savingsId: Long): List { return baseApiManager.clientChargeApi.getSavingsAccountChargeList(savingsId) } @@ -205,7 +205,7 @@ class DataManager @Inject constructor( return baseApiManager.registrationApi.verifyUser(userVerify) } - suspend fun clientLocalCharges(): Response?> = databaseHelper.clientCharges() + suspend fun clientLocalCharges(): Page = databaseHelper.clientCharges() fun notifications(): List = databaseHelper.notifications() diff --git a/app/src/main/java/org/mifos/mobile/api/local/DatabaseHelper.kt b/app/src/main/java/org/mifos/mobile/api/local/DatabaseHelper.kt index 7818d3a08..024e3040c 100644 --- a/app/src/main/java/org/mifos/mobile/api/local/DatabaseHelper.kt +++ b/app/src/main/java/org/mifos/mobile/api/local/DatabaseHelper.kt @@ -2,6 +2,8 @@ package org.mifos.mobile.api.local import com.raizlabs.android.dbflow.sql.language.SQLite import io.reactivex.Observable +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow import org.mifos.mobile.models.Charge import org.mifos.mobile.models.Page import org.mifos.mobile.models.notification.MifosNotification @@ -17,21 +19,21 @@ import javax.inject.Singleton */ @Singleton class DatabaseHelper @Inject constructor() { - fun syncCharges(charges: Page?): Response?> { + fun syncCharges(charges: Page?): Page? { if (charges != null) { for (charge in charges.pageItems) - charge?.save() + charge.save() } - return Response.success(charges) + return charges } - fun clientCharges(): Response?> { + fun clientCharges(): Page { val charges = SQLite.select() .from(Charge::class.java) .queryList() val chargePage = Page() chargePage.pageItems = charges - return Response.success(chargePage) + return chargePage } fun notifications(): List { diff --git a/app/src/main/java/org/mifos/mobile/api/services/ClientChargeService.kt b/app/src/main/java/org/mifos/mobile/api/services/ClientChargeService.kt index dce4d237d..6c080b28d 100644 --- a/app/src/main/java/org/mifos/mobile/api/services/ClientChargeService.kt +++ b/app/src/main/java/org/mifos/mobile/api/services/ClientChargeService.kt @@ -14,11 +14,11 @@ import retrofit2.http.Path interface ClientChargeService { @GET(ApiEndPoints.CLIENTS + "/{clientId}/charges") - suspend fun getClientChargeList(@Path("clientId") clientId: Long?): Response?>? + suspend fun getClientChargeList(@Path("clientId") clientId: Long?): Page @GET(ApiEndPoints.LOANS + "/{loanId}/charges") - suspend fun getLoanAccountChargeList(@Path("loanId") loanId: Long?): Response?>? + suspend fun getLoanAccountChargeList(@Path("loanId") loanId: Long?): List @GET(ApiEndPoints.SAVINGS_ACCOUNTS + "/{savingsId}/charges") - suspend fun getSavingsAccountChargeList(@Path("savingsId") savingsId: Long?): Response?>? + suspend fun getSavingsAccountChargeList(@Path("savingsId") savingsId: Long?): List } diff --git a/app/src/main/java/org/mifos/mobile/repositories/ClientChargeRepository.kt b/app/src/main/java/org/mifos/mobile/repositories/ClientChargeRepository.kt index e69d77226..0ed6d793e 100644 --- a/app/src/main/java/org/mifos/mobile/repositories/ClientChargeRepository.kt +++ b/app/src/main/java/org/mifos/mobile/repositories/ClientChargeRepository.kt @@ -1,13 +1,13 @@ package org.mifos.mobile.repositories +import kotlinx.coroutines.flow.Flow import org.mifos.mobile.models.Charge import org.mifos.mobile.models.Page -import retrofit2.Response interface ClientChargeRepository { - suspend fun getClientCharges(clientId: Long): Response?>? - suspend fun getLoanCharges(loanId: Long): Response?>? - suspend fun getSavingsCharges(savingsId: Long): Response?>? - suspend fun clientLocalCharges(): Response?> + suspend fun getClientCharges(clientId: Long): Flow> + suspend fun getLoanCharges(loanId: Long): Flow> + suspend fun getSavingsCharges(savingsId: Long): Flow> + suspend fun clientLocalCharges(): Flow> } \ No newline at end of file diff --git a/app/src/main/java/org/mifos/mobile/repositories/ClientChargeRepositoryImp.kt b/app/src/main/java/org/mifos/mobile/repositories/ClientChargeRepositoryImp.kt index ad7a0cd15..2bdfef2eb 100644 --- a/app/src/main/java/org/mifos/mobile/repositories/ClientChargeRepositoryImp.kt +++ b/app/src/main/java/org/mifos/mobile/repositories/ClientChargeRepositoryImp.kt @@ -1,5 +1,7 @@ package org.mifos.mobile.repositories +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow import org.mifos.mobile.api.DataManager import org.mifos.mobile.models.Charge import org.mifos.mobile.models.Page @@ -9,19 +11,27 @@ import javax.inject.Inject class ClientChargeRepositoryImp @Inject constructor(private val dataManager: DataManager) : ClientChargeRepository { - override suspend fun getClientCharges(clientId: Long): Response?>? { - return dataManager.getClientCharges(clientId) + override suspend fun getClientCharges(clientId: Long): Flow> { + return flow { + emit(dataManager.getClientCharges(clientId)) + } } - override suspend fun getLoanCharges(loanId: Long): Response?>? { - return dataManager.getLoanCharges(loanId) + override suspend fun getLoanCharges(loanId: Long): Flow> { + return flow { + emit(dataManager.getLoanCharges(loanId)) + } } - override suspend fun getSavingsCharges(savingsId: Long): Response?>? { - return dataManager.getSavingsCharges(savingsId) + override suspend fun getSavingsCharges(savingsId: Long): Flow> { + return flow { + emit(dataManager.getSavingsCharges(savingsId)) + } } - override suspend fun clientLocalCharges(): Response?> { - return dataManager.clientLocalCharges() + override suspend fun clientLocalCharges(): Flow> { + return flow { + emit(dataManager.clientLocalCharges()) + } } } \ No newline at end of file diff --git a/app/src/main/java/org/mifos/mobile/ui/fragments/ClientChargeFragment.kt b/app/src/main/java/org/mifos/mobile/ui/fragments/ClientChargeFragment.kt index 14a1fd4c2..59db3f0a4 100644 --- a/app/src/main/java/org/mifos/mobile/ui/fragments/ClientChargeFragment.kt +++ b/app/src/main/java/org/mifos/mobile/ui/fragments/ClientChargeFragment.kt @@ -6,10 +6,14 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast -import androidx.lifecycle.ViewModelProvider +import androidx.fragment.app.viewModels +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle import androidx.recyclerview.widget.LinearLayoutManager import com.github.therajanmaurya.sweeterror.SweetUIErrorHandler import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch import org.mifos.mobile.R import org.mifos.mobile.databinding.FragmentClientChargeBinding import org.mifos.mobile.models.Charge @@ -21,7 +25,6 @@ import org.mifos.mobile.utils.Constants import org.mifos.mobile.utils.Network import org.mifos.mobile.utils.Toaster import org.mifos.mobile.viewModels.ClientChargeViewModel -import java.util.* /** * @author Vishwajeet @@ -33,7 +36,7 @@ class ClientChargeFragment : BaseFragment() { private var _binding: FragmentClientChargeBinding? = null private val binding get() = _binding!! - private lateinit var viewModel: ClientChargeViewModel + private val viewModel: ClientChargeViewModel by viewModels() private var clientChargeAdapter: ClientChargeAdapter? = null private var id: Long? = 0 @@ -55,7 +58,6 @@ class ClientChargeFragment : BaseFragment() { savedInstanceState: Bundle?, ): View { _binding = FragmentClientChargeBinding.inflate(inflater, container, false) - viewModel = ViewModelProvider(this)[ClientChargeViewModel::class.java] clientChargeAdapter = ClientChargeAdapter(::onItemClick) setToolbarTitle(getString(R.string.charges)) sweetUIErrorHandler = SweetUIErrorHandler(activity, binding.root) @@ -78,16 +80,23 @@ class ClientChargeFragment : BaseFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - viewModel.clientChargeUiState.observe(viewLifecycleOwner) { - when (it) { - is ClientChargeUiState.Loading -> showProgress() - is ClientChargeUiState.ShowError -> { - hideProgress() - showErrorFetchingClientCharges(getString(it.message)) - } - is ClientChargeUiState.ShowClientCharges -> { - hideProgress() - showClientCharges(it.charges) + viewLifecycleOwner.lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.clientChargeUiState.collect { + when (it) { + is ClientChargeUiState.Loading -> showProgress() + is ClientChargeUiState.ShowError -> { + hideProgress() + showErrorFetchingClientCharges(getString(it.message)) + } + + is ClientChargeUiState.ShowClientCharges -> { + hideProgress() + showClientCharges(it.charges) + } + + is ClientChargeUiState.Initial -> {} + } } } } @@ -101,9 +110,11 @@ class ClientChargeFragment : BaseFragment() { super.onSaveInstanceState(outState) outState.putParcelableArrayList( Constants.CHARGES, - ArrayList( - clientChargeList, - ), + clientChargeList?.let { + ArrayList( + it, + ) + }, ) } diff --git a/app/src/main/java/org/mifos/mobile/utils/ClientChargeUiState.kt b/app/src/main/java/org/mifos/mobile/utils/ClientChargeUiState.kt index 698f1eccf..6582f8156 100644 --- a/app/src/main/java/org/mifos/mobile/utils/ClientChargeUiState.kt +++ b/app/src/main/java/org/mifos/mobile/utils/ClientChargeUiState.kt @@ -3,6 +3,7 @@ package org.mifos.mobile.utils import org.mifos.mobile.models.Charge sealed class ClientChargeUiState { + object Initial : ClientChargeUiState() object Loading : ClientChargeUiState() data class ShowError(val message: Int) : ClientChargeUiState() data class ShowClientCharges(val charges: List) : ClientChargeUiState() diff --git a/app/src/main/java/org/mifos/mobile/viewModels/ClientChargeViewModel.kt b/app/src/main/java/org/mifos/mobile/viewModels/ClientChargeViewModel.kt index d7ba9757e..3803adc5a 100644 --- a/app/src/main/java/org/mifos/mobile/viewModels/ClientChargeViewModel.kt +++ b/app/src/main/java/org/mifos/mobile/viewModels/ClientChargeViewModel.kt @@ -1,9 +1,11 @@ package org.mifos.mobile.viewModels -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.catch import kotlinx.coroutines.launch import org.mifos.mobile.R import org.mifos.mobile.repositories.ClientChargeRepository @@ -14,24 +16,19 @@ import javax.inject.Inject class ClientChargeViewModel @Inject constructor(private val clientChargeRepositoryImp: ClientChargeRepository) : ViewModel() { - private val _clientChargeUiState = MutableLiveData() - val clientChargeUiState get() = _clientChargeUiState + private val _clientChargeUiState = + MutableStateFlow(ClientChargeUiState.Initial) + + val clientChargeUiState: StateFlow get() = _clientChargeUiState fun loadClientCharges(clientId: Long) { viewModelScope.launch { _clientChargeUiState.value = ClientChargeUiState.Loading - try { - val response = clientChargeRepositoryImp.getClientCharges(clientId) - if (response?.isSuccessful == true) { - _clientChargeUiState.value = - response.body()?.pageItems?.let { ClientChargeUiState.ShowClientCharges(it) } - } else { - _clientChargeUiState.value = - ClientChargeUiState.ShowError(R.string.client_charges) - } - } catch (e: Throwable) { + clientChargeRepositoryImp.getClientCharges(clientId).catch { _clientChargeUiState.value = ClientChargeUiState.ShowError(R.string.client_charges) + }.collect { + _clientChargeUiState.value = ClientChargeUiState.ShowClientCharges(it.pageItems) } } } @@ -39,18 +36,11 @@ class ClientChargeViewModel @Inject constructor(private val clientChargeReposito fun loadLoanAccountCharges(loanId: Long) { viewModelScope.launch { _clientChargeUiState.value = ClientChargeUiState.Loading - try { - val response = clientChargeRepositoryImp.getLoanCharges(loanId) - if (response?.isSuccessful == true) { - _clientChargeUiState.value = response.body() - ?.let { ClientChargeUiState.ShowClientCharges(it) } - } else { - _clientChargeUiState.value = - ClientChargeUiState.ShowError(R.string.client_charges) - } - } catch (e: Throwable) { + clientChargeRepositoryImp.getLoanCharges(loanId).catch { _clientChargeUiState.value = ClientChargeUiState.ShowError(R.string.client_charges) + }.collect { + _clientChargeUiState.value = ClientChargeUiState.ShowClientCharges(it) } } } @@ -58,18 +48,11 @@ class ClientChargeViewModel @Inject constructor(private val clientChargeReposito fun loadSavingsAccountCharges(savingsId: Long) { viewModelScope.launch { _clientChargeUiState.value = ClientChargeUiState.Loading - try { - val response = clientChargeRepositoryImp.getSavingsCharges(savingsId) - if (response?.isSuccessful == true) { - _clientChargeUiState.value = response.body() - ?.let { ClientChargeUiState.ShowClientCharges(it) } - } else { - _clientChargeUiState.value = - ClientChargeUiState.ShowError(R.string.client_charges) - } - } catch (e: Throwable) { + clientChargeRepositoryImp.getSavingsCharges(savingsId).catch { _clientChargeUiState.value = ClientChargeUiState.ShowError(R.string.client_charges) + }.collect { + _clientChargeUiState.value = ClientChargeUiState.ShowClientCharges(it) } } } @@ -77,18 +60,11 @@ class ClientChargeViewModel @Inject constructor(private val clientChargeReposito fun loadClientLocalCharges() { viewModelScope.launch { _clientChargeUiState.value = ClientChargeUiState.Loading - try { - val response = clientChargeRepositoryImp.clientLocalCharges() - if (response.isSuccessful) { - _clientChargeUiState.value = - response.body()?.pageItems?.let { ClientChargeUiState.ShowClientCharges(it) } - } else { - _clientChargeUiState.value = - ClientChargeUiState.ShowError(R.string.client_charges) - } - } catch (e: Throwable) { + clientChargeRepositoryImp.clientLocalCharges().catch { _clientChargeUiState.value = ClientChargeUiState.ShowError(R.string.client_charges) + }.collect { + _clientChargeUiState.value = ClientChargeUiState.ShowClientCharges(it.pageItems) } } }