Magrate schedule domain to flow
This commit is contained in:
@@ -43,4 +43,5 @@ dependencies {
|
||||
|
||||
implementation(project(":core:network"))
|
||||
implementation(project(":core:database"))
|
||||
implementation(project(":core:common"))
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
package ru.fincode.tsudesk.feature.schedule.data
|
||||
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import ru.fincode.tsudesk.core.common.model.DataResult
|
||||
import ru.fincode.tsudesk.core.common.model.DataResult.Error
|
||||
import ru.fincode.tsudesk.core.network.model.NetworkResult
|
||||
import ru.fincode.tsudesk.core.network.model.map
|
||||
import ru.fincode.tsudesk.feature.schedule.data.datasource.ScheduleLocalDataSource
|
||||
@@ -7,6 +15,7 @@ import ru.fincode.tsudesk.feature.schedule.data.datasource.ScheduleRemoteDataSou
|
||||
import ru.fincode.tsudesk.feature.schedule.data.mapper.ScheduleCacheKey
|
||||
import ru.fincode.tsudesk.feature.schedule.data.mapper.ScheduleNetworkMapper
|
||||
import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity
|
||||
import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleType
|
||||
import ru.fincode.tsudesk.feature.schedule.domain.repository.ScheduleRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -16,19 +25,50 @@ class ScheduleRepositoryImpl @Inject constructor(
|
||||
private val mapper: ScheduleNetworkMapper
|
||||
) : ScheduleRepository {
|
||||
|
||||
override suspend fun loadScheduleByGroup(number: String): NetworkResult<ScheduleEntity> {
|
||||
val result = remote.loadScheduleByGroup(number).map(mapper::invoke)
|
||||
if (result is NetworkResult.Success) {
|
||||
local.saveSchedule(ScheduleCacheKey.group(number), result.data)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
override fun observeSchedule(type: ScheduleType): Flow<DataResult<ScheduleEntity>> =
|
||||
channelFlow {
|
||||
val key = when (type) {
|
||||
is ScheduleType.Group -> ScheduleCacheKey.group(type.number)
|
||||
is ScheduleType.Teacher -> ScheduleCacheKey.teacher(type.name)
|
||||
}
|
||||
|
||||
override suspend fun loadScheduleByTeacher(name: String): NetworkResult<ScheduleEntity> {
|
||||
val result = remote.loadScheduleByTeacher(name).map(mapper::invoke)
|
||||
if (result is NetworkResult.Success) {
|
||||
local.saveSchedule(ScheduleCacheKey.teacher(name), result.data)
|
||||
// кэш -> UI
|
||||
val cacheJob = launch {
|
||||
local.observeSchedule(key).collect { cached ->
|
||||
if (cached != null) send(DataResult.Cache(cached))
|
||||
}
|
||||
}
|
||||
|
||||
val networkResult: NetworkResult<ScheduleEntity> = when (type) {
|
||||
is ScheduleType.Group ->
|
||||
remote.loadScheduleByGroup(type.number).map(mapper::invoke)
|
||||
|
||||
is ScheduleType.Teacher ->
|
||||
remote.loadScheduleByTeacher(type.name).map(mapper::invoke)
|
||||
}
|
||||
|
||||
when (networkResult) {
|
||||
is NetworkResult.Success -> {
|
||||
// (опционально) сразу отдать сетевой результат
|
||||
send(DataResult.Network(networkResult.data))
|
||||
|
||||
// single source of truth -> сохраняем в БД
|
||||
local.saveSchedule(key, networkResult.data)
|
||||
|
||||
// дать Room время эмитнуть обновление
|
||||
kotlinx.coroutines.yield()
|
||||
|
||||
// закрываем поток по твоему требованию
|
||||
close()
|
||||
}
|
||||
|
||||
is NetworkResult.Error -> {
|
||||
send(Error(Throwable(networkResult.error.toString())))
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
awaitClose { cacheJob.cancel() }
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package ru.fincode.tsudesk.feature.schedule.data.datasource
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity
|
||||
|
||||
interface ScheduleLocalDataSource {
|
||||
suspend fun saveSchedule(key: String, schedule: ScheduleEntity)
|
||||
suspend fun loadSchedule(key: String): ScheduleEntity?
|
||||
fun observeSchedule(key: String): Flow<ScheduleEntity?>
|
||||
suspend fun removeSchedule(key: String)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package ru.fincode.tsudesk.feature.schedule.data.local
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import ru.fincode.tsudesk.core.database.schedule.ScheduleDao
|
||||
import ru.fincode.tsudesk.feature.schedule.data.datasource.ScheduleLocalDataSource
|
||||
import ru.fincode.tsudesk.feature.schedule.data.mapper.toCache
|
||||
@@ -22,6 +24,13 @@ class ScheduleLocalDataSourceImpl @Inject constructor(
|
||||
return schedule.toDomain(lessons)
|
||||
}
|
||||
|
||||
override fun observeSchedule(key: String): Flow<ScheduleEntity?> {
|
||||
return dao.observeSchedule(key)
|
||||
.combine(dao.observeLessons(key)) { schedule, lessons ->
|
||||
schedule?.toDomain(lessons)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun removeSchedule(key: String) {
|
||||
dao.deleteLessonsByKey(key)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package ru.fincode.tsudesk.feature.schedule.domain.repository
|
||||
|
||||
import ru.fincode.tsudesk.core.network.model.NetworkResult
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import ru.fincode.tsudesk.core.common.model.DataResult
|
||||
import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity
|
||||
import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleType
|
||||
|
||||
interface ScheduleRepository {
|
||||
suspend fun loadScheduleByGroup(number: String): NetworkResult<ScheduleEntity>
|
||||
suspend fun loadScheduleByTeacher(name: String): NetworkResult<ScheduleEntity>
|
||||
fun observeSchedule(type: ScheduleType): Flow<DataResult<ScheduleEntity>>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ru.fincode.tsudesk.feature.schedule.domain.usecase
|
||||
|
||||
import ru.fincode.tsudesk.core.network.model.NetworkResult
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import ru.fincode.tsudesk.core.common.model.DataResult
|
||||
import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity
|
||||
import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleType
|
||||
import ru.fincode.tsudesk.feature.schedule.domain.repository.ScheduleRepository
|
||||
@@ -9,8 +10,6 @@ import javax.inject.Inject
|
||||
class GetScheduleUseCase @Inject constructor(
|
||||
private val repository: ScheduleRepository
|
||||
) {
|
||||
suspend operator fun invoke(type: ScheduleType): NetworkResult<ScheduleEntity> = when (type) {
|
||||
is ScheduleType.Group -> repository.loadScheduleByGroup(type.number)
|
||||
is ScheduleType.Teacher -> repository.loadScheduleByTeacher(type.name)
|
||||
}
|
||||
operator fun invoke(type: ScheduleType): Flow<DataResult<ScheduleEntity>> =
|
||||
repository.observeSchedule(type)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user