Fetch icon and thumbnail for completed task to prevent stale data
The data returned from getAllTaskData can sometimes replace recently fetched thumbnail and icon data with a null value due to a race condition. This occurs when getAllTaskData results are returned after, or at the same time as, the thumbnail and icon data is fetched. Consequently, the information displayed to the user is incorrect and remains so until the user re-enters Overview or scrolls. To address this issue, we propose to re-request the task data for requests that have already been completed. Change-Id: I99ee7f38abab3c283c9f82bce7b1d069575ddc6e Fix: 392069389 Doc: go/launcher-overview-unified-taskviewmodel Flag: com.android.launcher3.enable_refactor_task_thumbnail Test: OverviewImageTests Test: TasksRepositoryTest
This commit is contained in:
@@ -52,37 +52,29 @@ class TasksRepository(
|
||||
override fun getAllTaskData(forceRefresh: Boolean): Flow<List<Task>> {
|
||||
if (forceRefresh) {
|
||||
recentsModel.getTasks { newTaskList ->
|
||||
val oldTaskMap = tasks.value
|
||||
val recentTasks =
|
||||
newTaskList
|
||||
.flatMap { groupTask -> groupTask.tasks }
|
||||
.associateBy { it.key.id }
|
||||
.also { newTaskMap ->
|
||||
// Clean tasks that are not in the latest group tasks list.
|
||||
val tasksNoLongerVisible = oldTaskMap.keys.subtract(newTaskMap.keys)
|
||||
val tasksNoLongerVisible = tasks.value.keys.subtract(newTaskMap.keys)
|
||||
removeTasks(tasksNoLongerVisible)
|
||||
|
||||
// Use pre-loaded thumbnail data and icon from the previous list.
|
||||
// This reduces the Thumbnail loading time in the Overview and prevent
|
||||
// empty thumbnail and icon.
|
||||
val cache =
|
||||
taskRequests.keys
|
||||
.mapNotNull { key ->
|
||||
val task = oldTaskMap[key] ?: return@mapNotNull null
|
||||
key to Pair(task.thumbnail, task.icon)
|
||||
}
|
||||
.toMap()
|
||||
|
||||
newTaskMap.values.forEach { task ->
|
||||
task.thumbnail = task.thumbnail ?: cache[task.key.id]?.first
|
||||
task.icon = task.icon ?: cache[task.key.id]?.second
|
||||
}
|
||||
}
|
||||
tasks.value = MapForStateFlow(recentTasks)
|
||||
Log.d(
|
||||
TAG,
|
||||
"getAllTaskData: oldTasks ${oldTaskMap.keys}, newTasks: ${recentTasks.keys}",
|
||||
"getAllTaskData: oldTasks ${tasks.value.keys}, newTasks: ${recentTasks.keys}",
|
||||
)
|
||||
tasks.value = MapForStateFlow(recentTasks)
|
||||
|
||||
// Request data for completed tasks to prevent stale data.
|
||||
// This will prevent thumbnail and icon from being replaced and
|
||||
// null due to race condition.
|
||||
taskRequests.values.forEach { (taskKey, job) ->
|
||||
if (job.isCompleted) {
|
||||
requestTaskData(taskKey.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return tasks.map { it.values.toList() }
|
||||
|
||||
Reference in New Issue
Block a user