Introduce TaskViewsIterator and TaskViewsIterable
- Create TaskViewsIterator to iterate all the current TaskViews inside
RecentsView.
- Create TaskViewsIterable with TaskViewsIterator as its iterator.
- Create `mTaskViewsIterable`, an instance of TaskViewsIterable that
used to make the TaskViews iterable.
- Current `getTaskViews()` return `mTaskViewsIterable` directly.
- Change `getTaskViews()` to be a public function, thus it can be
used outside of the RecentsView.
Some follow-up work includes:
- Replace all the call sites of `getTaskViewAt(0)` with
`getFirstTaskView()`
- Replace `0` as the index of the first TaskView with
`getFirstTaskViewIndex()`
- Audit all the call sites of iterating the TaskViews, let them use
`getTaskViews()` or IterableTaskViews.iterator() if index is needed.
Flag: EXEMPT as no functionality changes
Bug: 379942019
Test: Ensure the TaskViews required are correct in the following
scrnarios:
1. Swiping up from home screen to enter overview with empty or
multiple tasks
2. Swiping up from a fullscreen app to enter overview with
one or multiple tasks
3. Dimissing one or multiple tasks, exit and enter overview w/o
newly opened tasks
4. Remvoing all the tasks, reenter overview w/o newly opened
tasks
Change-Id: I930ce92b7e0bc37005af74a58fd4c0ce3013e5cb
diff --git a/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt b/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt
index 7393de4..e3e2cde 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt
+++ b/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt
@@ -136,10 +136,6 @@
isTaskViewFullyVisible: (TaskView) -> Boolean,
): Boolean = taskViews.any { !it.isLargeTile && isTaskViewFullyVisible(it) }
- /** Returns the current list of [TaskView] children. */
- fun getTaskViews(taskViewCount: Int, requireTaskViewAt: (Int) -> TaskView): Iterable<TaskView> =
- (0 until taskViewCount).map(requireTaskViewAt)
-
/** Apply attachAlpha to all [TaskView] accordingly to different conditions. */
fun applyAttachAlpha(
taskViews: Iterable<TaskView>,
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index c2eae66..c9af856 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -237,12 +237,14 @@
import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource;
import kotlin.Unit;
+import kotlin.collections.CollectionsKt;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -848,6 +850,59 @@
private int mTaskViewCount = 0;
+ private final TaskViewsIterable mTaskViewsIterable = new TaskViewsIterable();
+
+ public class TaskViewsIterable implements Iterable<TaskView> {
+ @Override
+ public TaskViewsIterator iterator() {
+ return new TaskViewsIterator();
+ }
+ }
+
+ // An Iterator to iterate all the current TaskViews inside the RecentsView.
+ public class TaskViewsIterator implements Iterator<TaskView> {
+ // Refers to the index of the `TaskView` that will be returned when `next()` is called.
+ private int mNextIndex = 0;
+
+ // The "limit" of this iterator. This is the number of children of the RecentsView when
+ // the iterator was created. Adding & removing elements will invalidate the iteration
+ // anyway (and cause next() to throw) so saving this value will guarantee that the
+ // value of hasNext() remains stable and won't flap between true and false when elements
+ // are added and removed from the RecentsView.
+ private final int mLimit = getChildCount();
+
+ TaskViewsIterator() {
+ advanceIfNeeded();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return mNextIndex < mLimit && mNextIndex < getChildCount();
+ }
+
+ @Override
+ public TaskView next() {
+ if (!hasNext()) {
+ throw new IndexOutOfBoundsException(
+ String.format("mNextIndex: %d, child count: %d", mNextIndex,
+ getChildCount()));
+ }
+ TaskView taskView = requireTaskViewAt(mNextIndex);
+ mNextIndex++;
+ advanceIfNeeded();
+ return taskView;
+ }
+
+ // Advances `mNextIndex` until it either points to a `TaskView` or to the end of the
+ // Iterator.
+ private void advanceIfNeeded() {
+ while (mNextIndex < mLimit && mNextIndex < getChildCount() && !(getChildAt(
+ mNextIndex) instanceof TaskView)) {
+ mNextIndex++;
+ }
+ }
+ }
+
@Nullable
public TaskView getFirstTaskView() {
return mUtils.getFirstTaskView(getTaskViews());
@@ -2074,14 +2129,11 @@
}
private void removeTasksViewsAndClearAllButton() {
- for (TaskView taskView : getTaskViews()) {
- if (isGestureActive() && taskView.isRunningTask()) {
- // This handles an edge case where applyLoadPlan happens during a gesture when the
- // only Task is one with excludeFromRecents, in which case we should not remove it.
- continue;
- }
- removeView(taskView);
- }
+ // This handles an edge case where applyLoadPlan happens during a gesture when the only
+ // Task is one with excludeFromRecents, in which case we should not remove it.
+ CollectionsKt
+ .filter(getTaskViews(), taskView -> !isGestureActive() || !taskView.isRunningTask())
+ .forEach(this::removeView);
if (getTaskViewCount() == 0 && indexOfChild(mClearAllButton) != -1) {
removeView(mClearAllButton);
}
@@ -4721,10 +4773,10 @@
}
/**
- * Returns the current list of [TaskView] children.
+ * Returns iterable [TaskView] children.
*/
- public Iterable<TaskView> getTaskViews() {
- return mUtils.getTaskViews(getTaskViewCount(), this::requireTaskViewAt);
+ public TaskViewsIterable getTaskViews() {
+ return mTaskViewsIterable;
}
public void setOnEmptyMessageUpdatedListener(OnEmptyMessageUpdatedListener listener) {