Skip to content

Commit

Permalink
Merge pull request #6 from AliElDerawi/coroutines-cancellation-handling
Browse files Browse the repository at this point in the history
feat: ensure that the coroutine terminates and the Job is canceled wh…
  • Loading branch information
AliElDerawi authored Jan 6, 2025
2 parents aa796fd + 4353a93 commit e6b6f51
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import com.google.android.gms.location.LocationServices
import com.udacity.project4.data.dto.ReminderDataSource
import com.udacity.project4.data.geofence.GeofenceTransitionsWorker
import com.udacity.project4.data.local.LocalDB
import com.udacity.project4.data.local.RemindersLocalRepository
import com.udacity.project4.data.repository.RemindersRepository
import com.udacity.project4.features.authentication.viewModel.AuthenticationViewModel
import com.udacity.project4.features.main.view.MainActivity
import com.udacity.project4.features.main.viewModel.MainViewModel
Expand Down Expand Up @@ -75,7 +75,7 @@ import org.robolectric.annotation.Config
@LargeTest
class AppNavigationTest : AutoCloseKoinTest() {

private lateinit var tasksRepository: RemindersLocalRepository
private lateinit var tasksRepository: RemindersRepository
// An Idling Resource that waits for Data Binding to have no pending bindings
private val dataBindingIdlingResource = DataBindingIdlingResource()
private lateinit var appContext: Application
Expand All @@ -93,10 +93,10 @@ class AppNavigationTest : AutoCloseKoinTest() {
workerOf(::FetchAddressWorker)
//Declare singleton definitions to be later injected using by inject()
single { SaveReminderViewModel(get(), get(),get()) }
single { RemindersLocalRepository(get(),Dispatchers.Unconfined,get()) }
single { RemindersRepository(get(),Dispatchers.Unconfined,get()) }
single { LocalDB.createRemindersDao(appContext) }
single { MainViewModel(get()) }
single<ReminderDataSource> { get<RemindersLocalRepository>() }
single<ReminderDataSource> { get<RemindersRepository>() }
single { LocationServices.getFusedLocationProviderClient(appContext) }
single { LocationServices.getGeofencingClient(appContext) }
single { MyResultIntentReceiver(Handler(appContext.mainLooper)) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import androidx.test.filters.MediumTest
import com.google.android.gms.location.LocationServices
import com.udacity.project4.R
import com.udacity.project4.data.dto.ReminderDTO
import com.udacity.project4.data.local.RemindersLocalRepository
import com.udacity.project4.data.repository.RemindersRepository
import com.udacity.project4.data.dto.Result
import com.udacity.project4.data.local.RemindersDatabase
import com.udacity.project4.data.model.ReminderDataItem
Expand Down Expand Up @@ -40,7 +40,7 @@ class RemindersLocalRepositoryTest : AutoCloseKoinTest() {

// TODO - Completed: Add testing implementation to the RemindersLocalRepository.kt
private lateinit var database: RemindersDatabase
private lateinit var localDataSource: RemindersLocalRepository
private lateinit var localDataSource: RemindersRepository
// Executes each task synchronously using Architecture Components.
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
Expand All @@ -56,7 +56,7 @@ class RemindersLocalRepositoryTest : AutoCloseKoinTest() {
ApplicationProvider.getApplicationContext(), RemindersDatabase::class.java
).allowMainThreadQueries().build()
//
localDataSource = RemindersLocalRepository(
localDataSource = RemindersRepository(
database.reminderDao(), Dispatchers.Unconfined, LocationServices.getFusedLocationProviderClient(appContext)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import com.udacity.project4.R
import com.udacity.project4.data.dto.ReminderDataSource
import com.udacity.project4.data.geofence.GeofenceTransitionsWorker
import com.udacity.project4.data.local.LocalDB
import com.udacity.project4.data.local.RemindersLocalRepository
import com.udacity.project4.data.repository.RemindersRepository
import com.udacity.project4.features.authentication.viewModel.AuthenticationViewModel
import com.udacity.project4.features.main.view.MainActivity
import com.udacity.project4.features.main.viewModel.MainViewModel
Expand Down Expand Up @@ -98,7 +98,7 @@ class ReminderListFragmentTest : AutoCloseKoinTest() {
workerOf(::FetchAddressWorker)
single { SaveReminderViewModel(appContext, get() as FakeTestRepository, get()) }
single { MainViewModel(get()) }
single { RemindersLocalRepository(get(), Dispatchers.Unconfined, get()) }
single { RemindersRepository(get(), Dispatchers.Unconfined, get()) }
single { LocalDB.createRemindersDao(appContext) }
single { FakeTestRepository() }
single<ReminderDataSource> { get<FakeTestRepository>() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import com.udacity.project4.R
import com.udacity.project4.data.dto.ReminderDataSource
import com.udacity.project4.data.geofence.GeofenceTransitionsWorker
import com.udacity.project4.data.local.LocalDB
import com.udacity.project4.data.local.RemindersLocalRepository
import com.udacity.project4.data.repository.RemindersRepository
import com.udacity.project4.features.authentication.viewModel.AuthenticationViewModel
import com.udacity.project4.features.main.view.MainActivity
import com.udacity.project4.features.main.viewModel.MainViewModel
Expand Down Expand Up @@ -108,7 +108,7 @@ class SaveReminderFragmentTest : AutoCloseKoinTest() {
workerOf(::FetchAddressWorker)
single { SaveReminderViewModel(appContext, get() as FakeTestRepository, get()) }
single { MainViewModel(get()) }
single { RemindersLocalRepository(get(), Dispatchers.Unconfined, get()) }
single { RemindersRepository(get(), Dispatchers.Unconfined, get()) }
single { LocalDB.createRemindersDao(appContext) }
single { FakeTestRepository() }
single<ReminderDataSource> { get<FakeTestRepository>() }
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/java/com/udacity/project4/data/MyApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import com.google.android.gms.location.LocationServices
import com.udacity.project4.data.dto.ReminderDataSource
import com.udacity.project4.data.geofence.GeofenceTransitionsWorker
import com.udacity.project4.data.local.LocalDB
import com.udacity.project4.data.local.RemindersLocalRepository
import com.udacity.project4.data.repository.RemindersRepository
import com.udacity.project4.features.authentication.viewModel.AuthenticationViewModel
import com.udacity.project4.features.main.viewModel.MainViewModel
import com.udacity.project4.features.remindersList.viewModel.RemindersListViewModel
Expand Down Expand Up @@ -53,9 +53,9 @@ class MyApp : MultiDexApplication() {
//Declare singleton definitions to be later injected using by inject()
singleOf(::SaveReminderViewModel)
singleOf(::MainViewModel)
single { RemindersLocalRepository(get(), Dispatchers.IO, get()) }
single { RemindersRepository(get(), Dispatchers.IO, get()) }
single { LocalDB.createRemindersDao(this@MyApp) }
single<ReminderDataSource> { get<RemindersLocalRepository>() }
single<ReminderDataSource> { get<RemindersRepository>() }
single { LocationServices.getFusedLocationProviderClient(this@MyApp) }
single { LocationServices.getGeofencingClient(this@MyApp) }
single { MyResultIntentReceiver(Handler(Looper.getMainLooper())) }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.udacity.project4.data.local
package com.udacity.project4.data.repository

import android.location.Location
import com.google.android.gms.location.FusedLocationProviderClient
Expand All @@ -7,12 +7,13 @@ import com.udacity.project4.data.MyApp
import com.udacity.project4.data.dto.ReminderDataSource
import com.udacity.project4.data.dto.ReminderDTO
import com.udacity.project4.data.dto.Result
import com.udacity.project4.data.local.RemindersDao
import com.udacity.project4.utils.AppSharedMethods
import com.udacity.project4.utils.wrapEspressoIdlingResource
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.tasks.await
Expand All @@ -26,7 +27,7 @@ import timber.log.Timber
* @param remindersDao the dao that does the Room db operations
* @param ioDispatcher a coroutine dispatcher to offload the blocking IO tasks
*/
class RemindersLocalRepository(
class RemindersRepository(
private val remindersDao: RemindersDao,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO,
private val fusedLocationProviderClient: FusedLocationProviderClient
Expand Down Expand Up @@ -74,6 +75,7 @@ class RemindersLocalRepository(
MyApp.getInstance().getString(R.string.text_error_reminder_not_found)
)
} catch (ex: Exception) {
ensureActive()
Result.Error(ex.localizedMessage)
}
}
Expand All @@ -98,9 +100,11 @@ class RemindersLocalRepository(
val location = fusedLocationProviderClient.lastLocation.await()
Result.Success(flow { emit(location) })
} catch (e: SecurityException) {
ensureActive()
Timber.e(e)
Result.Error(e.localizedMessage)
} catch (e: Exception) {
ensureActive()
Result.Error(e.localizedMessage)
}
}
Expand Down

0 comments on commit e6b6f51

Please sign in to comment.