Skip to content

Commit

Permalink
Merge pull request #2271 from PratyushSingh07/notification-coroutineImp
Browse files Browse the repository at this point in the history
feat: implemented coroutines in notification viewmodel
  • Loading branch information
jawidMuhammadi authored Aug 17, 2023
2 parents cfbfdda + c0c849e commit 7999fc0
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 211 deletions.
5 changes: 3 additions & 2 deletions app/src/main/java/org/mifos/mobile/api/DataManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.mifos.mobile.api
import io.reactivex.Observable
import io.reactivex.ObservableSource
import io.reactivex.functions.Function
import kotlinx.coroutines.flow.Flow
import okhttp3.MediaType
import okhttp3.ResponseBody
import org.mifos.mobile.FakeRemoteDataSource
Expand Down Expand Up @@ -200,8 +201,8 @@ class DataManager @Inject constructor(

suspend fun clientLocalCharges(): Response<Page<Charge?>?> = databaseHelper.clientCharges()

val notifications: Observable<List<MifosNotification?>?>
get() = databaseHelper.notifications
fun notifications(): Flow<List<MifosNotification?>?> = databaseHelper.notifications()

val unreadNotificationsCount: Observable<Int>
get() = databaseHelper.unreadNotificationsCount

Expand Down
10 changes: 7 additions & 3 deletions app/src/main/java/org/mifos/mobile/api/local/DatabaseHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -34,15 +36,17 @@ class DatabaseHelper @Inject constructor() {
return Response.success(chargePage)
}

val notifications: Observable<List<MifosNotification?>?>
get() = Observable.defer {
fun notifications(): Flow<List<MifosNotification?>?> {
return flow {
deleteOldNotifications()
val notifications = SQLite.select()
.from(MifosNotification::class.java)
.queryList()
Collections.sort(notifications, NotificationComparator())
Observable.just(notifications)
emit(notifications)
}
}

val unreadNotificationsCount: Observable<Int>
get() = Observable.defer {
deleteOldNotifications()
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package org.mifos.mobile.repositories

import io.reactivex.Observable
import kotlinx.coroutines.flow.Flow
import org.mifos.mobile.models.notification.MifosNotification

interface NotificationRepository {

fun loadNotifications(): Observable<List<MifosNotification?>?>
suspend fun loadNotifications(): Flow<List<MifosNotification?>?>
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package org.mifos.mobile.repositories

import io.reactivex.Observable
import kotlinx.coroutines.flow.Flow
import org.mifos.mobile.api.DataManager
import org.mifos.mobile.models.notification.MifosNotification
import javax.inject.Inject

class NotificationRepositoryImp @Inject constructor(private val dataManager: DataManager) : NotificationRepository {
class NotificationRepositoryImp @Inject constructor(private val dataManager: DataManager) :
NotificationRepository {

override fun loadNotifications(): Observable<List<MifosNotification?>?> {
return dataManager.notifications
override suspend fun loadNotifications(): Flow<List<MifosNotification?>?> {
return dataManager.notifications()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,30 @@ package org.mifos.mobile.viewModels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.observers.DisposableObserver
import io.reactivex.schedulers.Schedulers
import org.mifos.mobile.utils.NotificationUiState
import org.mifos.mobile.models.notification.MifosNotification
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.launch
import org.mifos.mobile.repositories.NotificationRepository
import org.mifos.mobile.utils.NotificationUiState
import javax.inject.Inject

@HiltViewModel
class NotificationViewModel @Inject constructor(private val notificationRepositoryImp: NotificationRepository): ViewModel() {
private val compositeDisposables: CompositeDisposable = CompositeDisposable()
class NotificationViewModel @Inject constructor(private val notificationRepositoryImp: NotificationRepository) :
ViewModel() {

private val _notificationUiState = MutableLiveData<NotificationUiState>()
val notificationUiState : LiveData<NotificationUiState> get() = _notificationUiState
val notificationUiState: LiveData<NotificationUiState> get() = _notificationUiState

fun loadNotifications() {
_notificationUiState.value = NotificationUiState.Loading
notificationRepositoryImp.loadNotifications()
.observeOn(AndroidSchedulers.mainThread())
?.subscribeOn(Schedulers.io())
?.subscribeWith(object : DisposableObserver<List<MifosNotification?>?>() {
override fun onComplete() {}
override fun onError(e: Throwable) {
_notificationUiState.value = NotificationUiState.Error
}
override fun onNext(notificationModels: List<MifosNotification?>) {
_notificationUiState.value = NotificationUiState.LoadNotificationsSuccessful(notificationModels)
}
})?.let { compositeDisposables.add(it) }
}

override fun onCleared() {
super.onCleared()
compositeDisposables.clear()
viewModelScope.launch {
notificationRepositoryImp.loadNotifications().catch {
_notificationUiState.value = NotificationUiState.Error
}.collect { list ->
_notificationUiState.value =
list?.let { NotificationUiState.LoadNotificationsSuccessful(it) }
}
}
}
}
72 changes: 0 additions & 72 deletions app/src/test/java/org/mifos/mobile/NotificationPresenterTest.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
package org.mifos.mobile.repositories

import io.reactivex.Observable

import org.junit.Assert
import CoroutineTestRule
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mifos.mobile.api.DataManager
import org.mifos.mobile.models.notification.MifosNotification
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import org.mockito.junit.MockitoJUnitRunner

@RunWith(MockitoJUnitRunner::class)
@ExperimentalCoroutinesApi
class NotificationRepositoryImpTest {

@get:Rule
val coroutineTestRule = CoroutineTestRule()

@Mock
lateinit var dataManager: DataManager

Expand All @@ -28,33 +36,33 @@ class NotificationRepositoryImpTest {
}

@Test
fun testLoadNotifications_SuccessResponseReceivedFromDataManager_ReturnsSuccess() {
fun testLoadNotifications_SuccessResponseReceivedFromDataManager_ReturnsSuccess() = runBlocking {
val notificationList : List<MifosNotification?> = ArrayList()
val successResponse: Observable<List<MifosNotification?>?> =
Observable.just(notificationList)
Mockito.`when`(
dataManager.notifications
).thenReturn(successResponse)
dataManager.notifications()
).thenReturn(flowOf(notificationList))

val result = notificationRepositoryImp.loadNotifications()

Mockito.verify(dataManager).notifications
Assert.assertEquals(result, successResponse)
val notifications = notificationRepositoryImp.loadNotifications()

notifications.collect { result ->
assert(result == notificationList)
}
}

@Test
fun testLoadNotifications_ErrorResponseReceivedFromDataManager_ReturnsError() {
val errorResponse: Observable<List<MifosNotification?>?> =
Observable.error(Throwable("LoadNotifications Unsuccessful"))
Mockito.`when`(
dataManager.notifications
).thenReturn(errorResponse)
fun testLoadNotifications_ErrorResponseReceivedFromDataManager_ReturnsError() = runBlocking {
val dummyError = Exception("Dummy error")
`when`(dataManager.notifications()).thenThrow(dummyError)

val result = notificationRepositoryImp.loadNotifications()
val notifications = notificationRepositoryImp.loadNotifications()

Mockito.verify(dataManager).notifications
Assert.assertEquals(result, errorResponse)
try {
notifications.catch { exception ->
assert(exception == dummyError)
}
} catch (e: Exception) {
assert(e == dummyError)
}
}

}
Loading

0 comments on commit 7999fc0

Please sign in to comment.