Control logic for putting up loading UI

This CL introduces the logic to put up and bind loading task views while
the first phase of loading occurs (i.e. loading the number and order of
recents items).

Bug: 114136250
Test: Go to recents, see tasks loading
Change-Id: I59bdc0fccc7f309ea4cded175c04a464b5a3665e
This commit is contained in:
Kevin 2019-04-05 09:09:28 -07:00
parent ad56fdf1e2
commit fc6781992d
4 changed files with 57 additions and 8 deletions

View File

@ -42,6 +42,9 @@ public final class TaskActionController {
* @param viewHolder the task view holder to launch * @param viewHolder the task view holder to launch
*/ */
public void launchTask(TaskHolder viewHolder) { public void launchTask(TaskHolder viewHolder) {
if (viewHolder.getTask() == null) {
return;
}
TaskItemView itemView = (TaskItemView) (viewHolder.itemView); TaskItemView itemView = (TaskItemView) (viewHolder.itemView);
View v = itemView.getThumbnailView(); View v = itemView.getThumbnailView();
int left = 0; int left = 0;
@ -60,6 +63,9 @@ public final class TaskActionController {
* @param viewHolder the task view holder to remove * @param viewHolder the task view holder to remove
*/ */
public void removeTask(TaskHolder viewHolder) { public void removeTask(TaskHolder viewHolder) {
if (viewHolder.getTask() == null) {
return;
}
int position = viewHolder.getAdapterPosition(); int position = viewHolder.getAdapterPosition();
Task task = viewHolder.getTask(); Task task = viewHolder.getTask();
ActivityManagerWrapper.getInstance().removeTask(task.key.id); ActivityManagerWrapper.getInstance().removeTask(task.key.id);

View File

@ -28,6 +28,7 @@ import com.android.quickstep.views.TaskItemView;
import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.Task;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* Recycler view adapter that dynamically inflates and binds {@link TaskHolder} instances with the * Recycler view adapter that dynamically inflates and binds {@link TaskHolder} instances with the
@ -40,6 +41,7 @@ public final class TaskAdapter extends Adapter<TaskHolder> {
private final TaskListLoader mLoader; private final TaskListLoader mLoader;
private final ArrayMap<Integer, TaskItemView> mTaskIdToViewMap = new ArrayMap<>(); private final ArrayMap<Integer, TaskItemView> mTaskIdToViewMap = new ArrayMap<>();
private TaskActionController mTaskActionController; private TaskActionController mTaskActionController;
private boolean mIsShowingLoadingUi;
public TaskAdapter(@NonNull TaskListLoader loader) { public TaskAdapter(@NonNull TaskListLoader loader) {
mLoader = loader; mLoader = loader;
@ -49,6 +51,18 @@ public final class TaskAdapter extends Adapter<TaskHolder> {
mTaskActionController = taskActionController; mTaskActionController = taskActionController;
} }
/**
* Sets all positions in the task adapter to loading views, binding new views if necessary.
* This changes the task adapter's view of the data, so the appropriate notify events should be
* called in addition to this method to reflect the changes.
*
* @param isShowingLoadingUi true to bind loading task views to all positions, false to return
* to the real data
*/
public void setIsShowingLoadingUi(boolean isShowingLoadingUi) {
mIsShowingLoadingUi = isShowingLoadingUi;
}
/** /**
* Get task item view for a given task id if it's attached to the view. * Get task item view for a given task id if it's attached to the view.
* *
@ -70,6 +84,10 @@ public final class TaskAdapter extends Adapter<TaskHolder> {
@Override @Override
public void onBindViewHolder(TaskHolder holder, int position) { public void onBindViewHolder(TaskHolder holder, int position) {
if (mIsShowingLoadingUi) {
holder.bindEmptyUi();
return;
}
List<Task> tasks = mLoader.getCurrentTaskList(); List<Task> tasks = mLoader.getCurrentTaskList();
if (position >= tasks.size()) { if (position >= tasks.size()) {
// Task list has updated. // Task list has updated.
@ -79,13 +97,13 @@ public final class TaskAdapter extends Adapter<TaskHolder> {
holder.bindTask(task); holder.bindTask(task);
mLoader.loadTaskIconAndLabel(task, () -> { mLoader.loadTaskIconAndLabel(task, () -> {
// Ensure holder still has the same task. // Ensure holder still has the same task.
if (task.equals(holder.getTask())) { if (Objects.equals(task, holder.getTask())) {
holder.getTaskItemView().setIcon(task.icon); holder.getTaskItemView().setIcon(task.icon);
holder.getTaskItemView().setLabel(task.titleDescription); holder.getTaskItemView().setLabel(task.titleDescription);
} }
}); });
mLoader.loadTaskThumbnail(task, () -> { mLoader.loadTaskThumbnail(task, () -> {
if (task.equals(holder.getTask())) { if (Objects.equals(task, holder.getTask())) {
holder.getTaskItemView().setThumbnail(task.thumbnail.thumbnail); holder.getTaskItemView().setThumbnail(task.thumbnail.thumbnail);
} }
}); });
@ -93,16 +111,27 @@ public final class TaskAdapter extends Adapter<TaskHolder> {
@Override @Override
public void onViewAttachedToWindow(@NonNull TaskHolder holder) { public void onViewAttachedToWindow(@NonNull TaskHolder holder) {
if (holder.getTask() == null) {
return;
}
mTaskIdToViewMap.put(holder.getTask().key.id, (TaskItemView) holder.itemView); mTaskIdToViewMap.put(holder.getTask().key.id, (TaskItemView) holder.itemView);
} }
@Override @Override
public void onViewDetachedFromWindow(@NonNull TaskHolder holder) { public void onViewDetachedFromWindow(@NonNull TaskHolder holder) {
if (holder.getTask() == null) {
return;
}
mTaskIdToViewMap.remove(holder.getTask().key.id); mTaskIdToViewMap.remove(holder.getTask().key.id);
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return Math.min(mLoader.getCurrentTaskList().size(), MAX_TASKS_TO_DISPLAY); if (mIsShowingLoadingUi) {
// Show loading version of all items.
return MAX_TASKS_TO_DISPLAY;
} else {
return Math.min(mLoader.getCurrentTaskList().size(), MAX_TASKS_TO_DISPLAY);
}
} }
} }

View File

@ -15,7 +15,7 @@
*/ */
package com.android.quickstep; package com.android.quickstep;
import androidx.annotation.NonNull; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView.ViewHolder; import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import com.android.quickstep.views.TaskItemView; import com.android.quickstep.views.TaskItemView;
@ -50,11 +50,23 @@ public final class TaskHolder extends ViewHolder {
} }
/** /**
* Gets the task currently bound to this view * Bind a generic empty UI to the holder to make it clear that the item is loading/unbound and
* should not be expected to react to user input.
*/
public void bindEmptyUi() {
mTask = null;
// TODO: Set the task view to a loading, empty UI.
// Temporarily using the one below for visual confirmation but should be swapped out to new
// UI later.
mTaskItemView.resetTaskItemView();
}
/**
* Gets the task currently bound to this view. May be null if task holder is in a loading state.
* *
* @return the current task * @return the current task
*/ */
public @NonNull Task getTask() { public @Nullable Task getTask() {
return mTask; return mTask;
} }
} }

View File

@ -157,10 +157,12 @@ public final class IconRecentsView extends FrameLayout {
* becomes visible. * becomes visible.
*/ */
public void onBeginTransitionToOverview() { public void onBeginTransitionToOverview() {
mTaskAdapter.setIsShowingLoadingUi(true);
mTaskAdapter.notifyDataSetChanged();
// Load any task changes // Load any task changes
mTaskLoader.loadTaskList(tasks -> { mTaskLoader.loadTaskList(tasks -> {
// TODO: Put up some loading UI while task content is loading. May have to do something mTaskAdapter.setIsShowingLoadingUi(false);
// smarter when animating from app to overview. // TODO: Animate the loading UI out and the loaded data in.
mTaskAdapter.notifyDataSetChanged(); mTaskAdapter.notifyDataSetChanged();
}); });
} }