Мы используем Room
базу данных для хранения списка элементов, которые ожидают загрузки, каждый элемент имеет статус загрузки (WAITING
, UPLOADING
, UPLOADED
и FAILED
), нам нужно загружать их последовательно. Таким образом, у нас есть вариант использования, чтобы получить первый элемент WAITING
или UPLOADING
, и если мы обнаружили, что в базе данных есть элемент с состоянием UPLOADING
, то мы не будем загружать другой элемент до завершения загрузки, тогда мы получим первый элемент WAITING
в базу данных для загрузки. Мы обновляем статус элемента следующим образом doOnSubscribe(UPLOADING)
, onSuccess(UPLOADED)
и onError(FAILED)
. Нам нужно начать другую загрузку независимо от успеха или неудачи.
private fun startUpload() {
compositeDisposable.add(
// Check if another item is uploading
getFirstDeviceMediaByUploadStatusUseCase.execute(
GetFirstDeviceMediaByUploadStatusUseCase
.Params
.create(UploadStatus.UPLOADING))
.subscribeOn(executionThread.getIOThread())
.observeOn(executionThread.getMainThread())
.subscribe({
// If another item is uploading we do nothing
}, {
// If there is item with UPLOADING status then we will start upload first item waiting for upload
if (it is EmptyResultSetException) {
getFirstDeviceMediaByUploadStatusUseCase.execute(
GetFirstDeviceMediaByUploadStatusUseCase
.Params
.create(UploadStatus.WAITING))
.subscribeOn(executionThread.getIOThread())
.observeOn(executionThread.getMainThread())
.subscribe({ deviceMedia ->
// Start uploading
uploadDeviceMedia(deviceMedia)
}, {
VCLogger.i("No waiting files we should stop upload service")
stopForegroundService()
})
}
}))
}
private fun uploadDeviceMedia(deviceMedia: DeviceMediaEntity) {
compositeDisposable.add(
uploadDeviceMediaUseCase.execute(UploadDeviceMediaUseCase.Params.create(deviceMedia))
.subscribeOn(executionThread.getIOThread())
.observeOn(executionThread.getMainThread())
.doOnSubscribe {
VCLogger.i("Uploading... ${deviceMedia.path}")
deviceMedia.updatedAt = Date()
deviceMedia.uploadStatus = UploadStatus.UPLOADING
// Update device media status to UPLOADING
compositeDisposable.add(
updateDeviceMediaUseCase.execute(UpdateDeviceMediaUseCase.Params.create(deviceMedia))
.subscribeOn(executionThread.getIOThread())
.observeOn(executionThread.getMainThread())
.subscribe()
)
}
.subscribe({
VCLogger.i("Uploaded ${deviceMedia.path}")
deviceMedia.updatedAt = Date()
deviceMedia.uploadStatus = UploadStatus.UPLOADED
// Update device media status to UPLOADED then start upload another one
compositeDisposable.add(
updateDeviceMediaUseCase.execute(UpdateDeviceMediaUseCase.Params.create(deviceMedia))
.subscribeOn(executionThread.getIOThread())
.observeOn(executionThread.getMainThread())
.subscribe {
startUpload()
}
)
}, {
VCLogger.i("Failed to upload ${deviceMedia.path}")
deviceMedia.updatedAt = Date()
deviceMedia.uploadStatus = UploadStatus.FAILED
// Update device media status to FAILED then start upload another one
compositeDisposable.add(
updateDeviceMediaUseCase.execute(UpdateDeviceMediaUseCase.Params.create(deviceMedia))
.subscribeOn(executionThread.getIOThread())
.observeOn(executionThread.getMainThread())
.subscribe {
startUpload()
}
)
})
)
}
private fun stopForegroundService() {
VCLogger.i("Stop foreground service.")
// Stop foreground service and remove the notification.
stopForeground(true)
// Stop the foreground service.
stopSelf()
}
Каков наилучший подход для достижения такого поведения?