У меня есть набор больших задач, которые я хочу выполнить в фоновом режиме:
- Loding data
- Анализ группы файлов и сохранение их в
Room
По этой причине я создал уникальную цепочку Worker
с теми же tag
.
class GtfsStaticManager() {
private val workerManager = WorkManager.getInstance()
override fun load() {
val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
val inputData = GtfsStaticLoadDataWorker.inputData(staticUrl, cacheDir)
// 1. Loading data
val downloadWorkRequest = OneTimeWorkRequest.Builder(GtfsStaticLoadDataWorker::class.java)
.addTag("GTFS")
.setConstraints(constraints)
.setInputData(inputData)
.build()
// 2. List of Workers to parse and store data to the Room
val parseWorkers = GtfsFile.values().map {
OneTimeWorkRequest.Builder(GtfsStaticParseFileWorker::class.java)
.setInputData(GtfsStaticParseFileWorker.inputData(it.file, cacheDir + File.separator + "feed"))
.addTag("GTFS")
.build()
}
workerManager
.beginUniqueWork("GTFS", ExistingWorkPolicy.KEEP, downloadWorkRequest)
.then(parseWorkers)
.enqueue()
}
}
Все отлично работает, кроме одного: один из файлов имеет 4 миллиона записей иэто займет около 10-15 минут, чтобы закончить его.Через некоторое время я заметил, что он снова был поставлен в очередь НО , первое задание все еще выполнялось, в результате у меня есть 2 огромных задания, работающих в фоновом режиме, и, конечно, мои данные были продублированы.
Iследовал учебнику codelabs , я что-то пропустил?
Ниже мой Worker
с логикой синтаксического анализа:
class GtfsStaticParseFileWorker(
context: Context,
workerParameters: WorkerParameters
) : Worker(context, workerParameters) {
private val fileName: String get() = inputData.getString(FILE_NAME) ?: ""
private val cacheDir: String get() = inputData.getString(UNZIP_FOLDER) ?: ""
companion object {
private const val FILE_NAME = "FILE_NAME"
private const val UNZIP_FOLDER = "UNZIP_FOLDER"
fun inputData(fileName: String, cacheDir: String) = Data
.Builder()
.putString(FILE_NAME, fileName)
.putString(UNZIP_FOLDER, cacheDir)
.build()
}
override fun doWork(): Result {
val db = LvivTransportTrackerDataBase.getUpdateInstance(applicationContext)
val agencyRepository = AgencyRepository(db.agencyDao())
val calendarRepository = CalendarRepository(db.calendarDao())
val calendarDateRepository = CalendarDateRepository(db.calendarDateDao())
val routeRepository = RouteRepository(db.routeDao())
val stopTimeRepository = StopTimeRepository(db.stopTimeDao())
val stopRepository = StopRepository(db.stopDao())
val tripRepository = TripRepository(db.tripDao())
val file = File(cacheDir + File.separator + fileName)
val fileType = GtfsFile.from(fileName) ?: return Result.failure()
when (fileType) {
GtfsFile.Agency -> agencyRepository.deleteAll()
GtfsFile.CalendarDates -> calendarDateRepository.deleteAll()
GtfsFile.Calendar -> calendarRepository.deleteAll()
GtfsFile.Routes -> routeRepository.deleteAll()
GtfsFile.StopTimes -> stopTimeRepository.deleteAll()
GtfsFile.Stops -> stopRepository.deleteAll()
GtfsFile.Trips -> tripRepository.deleteAll()
}
FileInputStream(file).use { fileInputStream ->
InputStreamReader(fileInputStream).use inputStreamReader@{ inputStreamReader ->
val bufferedReader = BufferedReader(inputStreamReader)
val headers = bufferedReader.readLine()?.split(',') ?: return@inputStreamReader
var line: String? = bufferedReader.readLine()
while (line != null) {
val mapLine = headers.zip(line.split(',')).toMap()
Log.d("GtfsStaticParse", "$fileType: $line")
when (fileType) {
GtfsFile.Agency -> agencyRepository.create(AgencyEntity(mapLine))
GtfsFile.CalendarDates -> calendarDateRepository.create(CalendarDateEntity(mapLine))
GtfsFile.Calendar -> calendarRepository.create(CalendarEntity(mapLine))
GtfsFile.Routes -> routeRepository.create(RouteEntity(mapLine))
GtfsFile.StopTimes -> stopTimeRepository.create(StopTimeEntity(mapLine))
GtfsFile.Stops -> stopRepository.create(StopEntity(mapLine))
GtfsFile.Trips -> tripRepository.create(TripEntity(mapLine))
}
line = bufferedReader.readLine()
}
}
}
return Result.success()
}
}
PS моя зависимость implementation "android.arch.work:work-runtime:1.0.0"