diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2019-03-29 02:07:01 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2019-03-29 02:07:01 +0000 |
commit | 7c1d69e5154cb5845e948215dd4c3374159e1592 (patch) | |
tree | 71e0f927a0bf00072d6082c8fa8aa3d1f232112b /go | |
parent | 09b91447467ad401e994e6e215d9a5b770dbe2c3 (diff) | |
parent | b589241fd683cda2da005093c891a89b39fc08a3 (diff) | |
download | android_packages_apps_Trebuchet-7c1d69e5154cb5845e948215dd4c3374159e1592.tar.gz android_packages_apps_Trebuchet-7c1d69e5154cb5845e948215dd4c3374159e1592.tar.bz2 android_packages_apps_Trebuchet-7c1d69e5154cb5845e948215dd4c3374159e1592.zip |
Merge "Show ASAP for Recents Go and load content after" into ub-launcher3-master
Diffstat (limited to 'go')
4 files changed, 116 insertions, 69 deletions
diff --git a/go/quickstep/src/com/android/quickstep/TaskAdapter.java b/go/quickstep/src/com/android/quickstep/TaskAdapter.java index e56cc5125..c98eca622 100644 --- a/go/quickstep/src/com/android/quickstep/TaskAdapter.java +++ b/go/quickstep/src/com/android/quickstep/TaskAdapter.java @@ -75,8 +75,20 @@ public final class TaskAdapter extends Adapter<TaskHolder> { // Task list has updated. return; } - holder.bindTask(tasks.get(position)); - + Task task = tasks.get(position); + holder.bindTask(task); + mLoader.loadTaskIconAndLabel(task, () -> { + // Ensure holder still has the same task. + if (task.equals(holder.getTask())) { + holder.getTaskItemView().setIcon(task.icon); + holder.getTaskItemView().setLabel(task.titleDescription); + } + }); + mLoader.loadTaskThumbnail(task, () -> { + if (task.equals(holder.getTask())) { + holder.getTaskItemView().setThumbnail(task.thumbnail.thumbnail); + } + }); } @Override diff --git a/go/quickstep/src/com/android/quickstep/TaskHolder.java b/go/quickstep/src/com/android/quickstep/TaskHolder.java index a89229f2f..744afd766 100644 --- a/go/quickstep/src/com/android/quickstep/TaskHolder.java +++ b/go/quickstep/src/com/android/quickstep/TaskHolder.java @@ -35,17 +35,18 @@ public final class TaskHolder extends ViewHolder { mTaskItemView = itemView; } + public TaskItemView getTaskItemView() { + return mTaskItemView; + } + /** - * Bind task content to the view. This includes the task icon and title as well as binding - * input handlers such as which task to launch/remove. + * Bind a task to the holder, resetting the view and preparing it for content to load in. * * @param task the task to bind to the view */ public void bindTask(Task task) { mTask = task; - mTaskItemView.setLabel(task.titleDescription); - mTaskItemView.setIcon(task.icon); - mTaskItemView.setThumbnail(task.thumbnail.thumbnail); + mTaskItemView.resetTaskItemView(); } /** diff --git a/go/quickstep/src/com/android/quickstep/TaskListLoader.java b/go/quickstep/src/com/android/quickstep/TaskListLoader.java index c86c24e8f..1234989d2 100644 --- a/go/quickstep/src/com/android/quickstep/TaskListLoader.java +++ b/go/quickstep/src/com/android/quickstep/TaskListLoader.java @@ -25,7 +25,6 @@ import com.android.systemui.shared.recents.model.Task; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; /** @@ -39,35 +38,48 @@ public final class TaskListLoader { private ArrayList<Task> mTaskList = new ArrayList<>(); private int mTaskListChangeId; + private RecentsModel.TaskThumbnailChangeListener listener = (taskId, thumbnailData) -> { + Task foundTask = null; + for (Task task : mTaskList) { + if (task.key.id == taskId) { + foundTask = task; + break; + } + } + if (foundTask != null) { + foundTask.thumbnail = thumbnailData; + } + return foundTask; + }; public TaskListLoader(Context context) { mRecentsModel = RecentsModel.INSTANCE.get(context); + mRecentsModel.addThumbnailChangeListener(listener); } /** - * Returns the current task list as of the last completed load (see - * {@link #loadTaskList}) as a read-only list. This list of tasks is guaranteed to always have - * all its task content loaded. + * Returns the current task list as of the last completed load (see {@link #loadTaskList}) as a + * read-only list. This list of tasks is not guaranteed to have all content loaded. * - * @return the current list of tasks w/ all content loaded + * @return the current list of tasks */ public List<Task> getCurrentTaskList() { return Collections.unmodifiableList(mTaskList); } /** - * Fetches the most recent tasks and updates the task list asynchronously. In addition it - * loads the content for each task (icon and label). The callback and task list being updated - * only occur when all task content is fully loaded and up-to-date. + * Fetches the most recent tasks and updates the task list asynchronously. This call does not + * provide guarantees the task content (icon, thumbnail, label) are loaded but will fill in + * what it has. May run the callback immediately if there have been no changes in the task + * list. * - * @param onTasksLoadedCallback callback for when the tasks are fully loaded. Done on the UI - * thread + * @param onLoadedCallback callback to run when task list is loaded */ - public void loadTaskList(@Nullable Consumer<ArrayList<Task>> onTasksLoadedCallback) { + public void loadTaskList(@Nullable Consumer<ArrayList<Task>> onLoadedCallback) { if (mRecentsModel.isTaskListValid(mTaskListChangeId)) { // Current task list is already up to date. No need to update. - if (onTasksLoadedCallback != null) { - onTasksLoadedCallback.accept(mTaskList); + if (onLoadedCallback != null) { + onLoadedCallback.accept(mTaskList); } return; } @@ -76,16 +88,46 @@ public final class TaskListLoader { // Reverse tasks to put most recent at the bottom of the view Collections.reverse(tasks); // Load task content - loadTaskContents(tasks, () -> { - mTaskList = tasks; - if (onTasksLoadedCallback != null) { - onTasksLoadedCallback.accept(mTaskList); + for (Task task : tasks) { + int loadedPos = mTaskList.indexOf(task); + if (loadedPos == -1) { + continue; } - }); + Task loadedTask = mTaskList.get(loadedPos); + task.icon = loadedTask.icon; + task.titleDescription = loadedTask.titleDescription; + task.thumbnail = loadedTask.thumbnail; + } + mTaskList = tasks; + onLoadedCallback.accept(tasks); }); } /** + * Load task icon and label asynchronously if it is not already loaded in the task. If the task + * already has an icon, this calls the callback immediately. + * + * @param task task to update with icon + label + * @param onLoadedCallback callback to run when task has icon and label + */ + public void loadTaskIconAndLabel(Task task, @Nullable Runnable onLoadedCallback) { + mRecentsModel.getIconCache().updateIconInBackground(task, + loadedTask -> onLoadedCallback.run()); + } + + /** + * Load thumbnail asynchronously if not already loaded in the task. If the task already has a + * thumbnail or if the thumbnail is cached, this calls the callback immediately. + * + * @param task task to update with the thumbnail + * @param onLoadedCallback callback to run when task has thumbnail + */ + public void loadTaskThumbnail(Task task, @Nullable Runnable onLoadedCallback) { + mRecentsModel.getThumbnailCache().updateThumbnailInBackground(task, + thumbnail -> onLoadedCallback.run()); + } + + /** * Removes the task from the current task list. */ void removeTask(Task task) { @@ -98,42 +140,4 @@ public final class TaskListLoader { void clearAllTasks() { mTaskList.clear(); } - - /** - * Loads task content for a list of tasks, including the label, icon, and thumbnail. For content - * that isn't cached, load the content asynchronously in the background. - * - * @param tasksToLoad list of tasks that need to load their content - * @param onFullyLoadedCallback runnable to run after all tasks have loaded their content - */ - private void loadTaskContents(ArrayList<Task> tasksToLoad, - @Nullable Runnable onFullyLoadedCallback) { - // Make two load requests per task, one for the icon/title and one for the thumbnail. - AtomicInteger loadRequestsCount = new AtomicInteger(tasksToLoad.size() * 2); - Runnable itemLoadedRunnable = () -> { - if (loadRequestsCount.decrementAndGet() == 0 && onFullyLoadedCallback != null) { - onFullyLoadedCallback.run(); - } - }; - for (Task task : tasksToLoad) { - // Load icon and title. - int index = mTaskList.indexOf(task); - if (index >= 0) { - // If we've already loaded the task and have its content then just copy it over. - Task loadedTask = mTaskList.get(index); - task.titleDescription = loadedTask.titleDescription; - task.icon = loadedTask.icon; - itemLoadedRunnable.run(); - } else { - // Otherwise, load the content in the background. - mRecentsModel.getIconCache().updateIconInBackground(task, - loadedTask -> itemLoadedRunnable.run()); - } - - // Load the thumbnail. May return immediately and synchronously if the thumbnail is - // cached. - mRecentsModel.getThumbnailCache().updateThumbnailInBackground(task, - thumbnail -> itemLoadedRunnable.run()); - } - } } diff --git a/go/quickstep/src/com/android/quickstep/views/TaskItemView.java b/go/quickstep/src/com/android/quickstep/views/TaskItemView.java index 373f10791..d831b206a 100644 --- a/go/quickstep/src/com/android/quickstep/views/TaskItemView.java +++ b/go/quickstep/src/com/android/quickstep/views/TaskItemView.java @@ -17,6 +17,7 @@ package com.android.quickstep.views; import android.content.Context; import android.graphics.Bitmap; +import android.graphics.Color; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; @@ -24,6 +25,8 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.Nullable; + import com.android.launcher3.R; /** @@ -31,12 +34,16 @@ import com.android.launcher3.R; */ public final class TaskItemView extends LinearLayout { + private static final String DEFAULT_LABEL = "..."; + private final Drawable mDefaultIcon; private TextView mLabelView; private ImageView mIconView; private ImageView mThumbnailView; public TaskItemView(Context context, AttributeSet attrs) { super(context, attrs); + mDefaultIcon = context.getResources().getDrawable( + android.R.drawable.sym_def_app_icon, context.getTheme()); } @Override @@ -48,33 +55,56 @@ public final class TaskItemView extends LinearLayout { } /** - * Set the label for the task item. + * Resets task item view to default values. + */ + public void resetTaskItemView() { + setLabel(DEFAULT_LABEL); + setIcon(null); + setThumbnail(null); + } + + /** + * Set the label for the task item. Sets to a default label if null. * * @param label task label */ - public void setLabel(String label) { + public void setLabel(@Nullable String label) { + if (label == null) { + mLabelView.setText(DEFAULT_LABEL); + return; + } mLabelView.setText(label); } /** - * Set the icon for the task item. + * Set the icon for the task item. Sets to a default icon if null. * * @param icon task icon */ - public void setIcon(Drawable icon) { + public void setIcon(@Nullable Drawable icon) { // TODO: Scale the icon up based off the padding on the side // The icon proper is actually smaller than the drawable and has "padding" on the side for // the purpose of drawing the shadow, allowing the icon to pop up, so we need to scale the // view if we want the icon to be flush with the bottom of the thumbnail. + if (icon == null) { + mIconView.setImageDrawable(mDefaultIcon); + return; + } mIconView.setImageDrawable(icon); } /** - * Set the task thumbnail for the task. + * Set the task thumbnail for the task. Sets to a default thumbnail if null. * * @param thumbnail task thumbnail for the task */ - public void setThumbnail(Bitmap thumbnail) { + public void setThumbnail(@Nullable Bitmap thumbnail) { + if (thumbnail == null) { + mThumbnailView.setImageBitmap(null); + mThumbnailView.setBackgroundColor(Color.GRAY); + return; + } + mThumbnailView.setBackgroundColor(Color.TRANSPARENT); mThumbnailView.setImageBitmap(thumbnail); } |