Reuse TTV, recreating deps to get faster load times, lower mem usage
Use a ViewPool for DesktopTaskView for same reason. Fix: 369590189 Flag: com.android.launcher3.enable_refactor_task_thumbnail Test: Manually looking at slow-mo videos of home to overview Change-Id: I0335e4d0eea4841145815244bbbec19541f31c73
This commit is contained in:
@@ -113,6 +113,10 @@ class RecentsDependencies private constructor(private val appContext: Context) {
|
||||
instance =
|
||||
factory?.invoke(extras) as T ?: createDependency(modelClass, scopeId, extras)
|
||||
scope[modelClass.simpleName] = instance!!
|
||||
log(
|
||||
"instance of $modelClass" +
|
||||
" (${instance.hashCode()}) added to scope ${scope.scopeId}"
|
||||
)
|
||||
}
|
||||
}
|
||||
return instance!!
|
||||
@@ -148,6 +152,13 @@ class RecentsDependencies private constructor(private val appContext: Context) {
|
||||
fun getScope(scopeId: RecentsScopeId): RecentsDependenciesScope =
|
||||
scopes[scopeId] ?: createScope(scopeId)
|
||||
|
||||
fun removeScope(scope: Any) {
|
||||
val scopeId: RecentsScopeId = scope as? RecentsScopeId ?: scope.hashCode().toString()
|
||||
scopes[scopeId]?.close()
|
||||
scopes.remove(scopeId)
|
||||
log("Scope $scopeId removed")
|
||||
}
|
||||
|
||||
// TODO(b/353912757): Create a factory so we can prevent this method of growing indefinitely.
|
||||
// Each class should be responsible for providing a factory function to create a new instance.
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.android.launcher3.R
|
||||
import com.android.launcher3.Utilities
|
||||
import com.android.launcher3.util.ViewPool
|
||||
import com.android.quickstep.recents.di.RecentsDependencies
|
||||
import com.android.quickstep.recents.di.get
|
||||
import com.android.quickstep.recents.di.inject
|
||||
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.BackgroundOnly
|
||||
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
|
||||
@@ -54,7 +55,7 @@ import kotlinx.coroutines.flow.onEach
|
||||
class TaskThumbnailView : ConstraintLayout, ViewPool.Reusable {
|
||||
|
||||
private val viewData: TaskThumbnailViewData by RecentsDependencies.inject(this)
|
||||
private val viewModel: TaskThumbnailViewModel by RecentsDependencies.inject(this)
|
||||
private lateinit var viewModel: TaskThumbnailViewModel
|
||||
|
||||
private lateinit var viewAttachedScope: CoroutineScope
|
||||
|
||||
@@ -91,6 +92,7 @@ class TaskThumbnailView : ConstraintLayout, ViewPool.Reusable {
|
||||
super.onAttachedToWindow()
|
||||
viewAttachedScope =
|
||||
CoroutineScope(SupervisorJob() + Dispatchers.Main + CoroutineName("TaskThumbnailView"))
|
||||
viewModel = RecentsDependencies.get(this)
|
||||
viewModel.uiState
|
||||
.onEach { viewModelUiState ->
|
||||
Log.d(TAG, "viewModelUiState changed from $uiState to: $viewModelUiState")
|
||||
|
||||
@@ -41,14 +41,7 @@ class TaskOverlayHelper(val task: Task, val overlay: TaskOverlayFactory.TaskOver
|
||||
private lateinit var overlayInitializedScope: CoroutineScope
|
||||
private var uiState: TaskOverlayUiState = Disabled
|
||||
|
||||
private val viewModel: TaskOverlayViewModel by lazy {
|
||||
TaskOverlayViewModel(
|
||||
task = task,
|
||||
recentsViewData = RecentsDependencies.get(),
|
||||
getThumbnailPositionUseCase = RecentsDependencies.get(),
|
||||
recentTasksRepository = RecentsDependencies.get()
|
||||
)
|
||||
}
|
||||
private lateinit var viewModel: TaskOverlayViewModel
|
||||
|
||||
// TODO(b/331753115): TaskOverlay should listen for state changes and react.
|
||||
val enabledState: Enabled
|
||||
@@ -60,12 +53,19 @@ class TaskOverlayHelper(val task: Task, val overlay: TaskOverlayFactory.TaskOver
|
||||
viewModel.getThumbnailPositionState(
|
||||
overlay.snapshotView.width,
|
||||
overlay.snapshotView.height,
|
||||
overlay.snapshotView.isLayoutRtl
|
||||
overlay.snapshotView.isLayoutRtl,
|
||||
)
|
||||
|
||||
fun init() {
|
||||
overlayInitializedScope =
|
||||
CoroutineScope(SupervisorJob() + Dispatchers.Main + CoroutineName("TaskOverlayHelper"))
|
||||
viewModel =
|
||||
TaskOverlayViewModel(
|
||||
task = task,
|
||||
recentsViewData = RecentsDependencies.get(),
|
||||
getThumbnailPositionUseCase = RecentsDependencies.get(),
|
||||
recentTasksRepository = RecentsDependencies.get(),
|
||||
)
|
||||
viewModel.overlayState
|
||||
.onEach {
|
||||
uiState = it
|
||||
|
||||
@@ -25,7 +25,6 @@ import android.graphics.drawable.shapes.RoundRectShape
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.view.updateLayoutParams
|
||||
@@ -40,6 +39,7 @@ import com.android.launcher3.util.ViewPool
|
||||
import com.android.launcher3.util.rects.set
|
||||
import com.android.quickstep.BaseContainerInterface
|
||||
import com.android.quickstep.TaskOverlayFactory
|
||||
import com.android.quickstep.task.thumbnail.TaskThumbnailView
|
||||
import com.android.quickstep.util.RecentsOrientedState
|
||||
import com.android.systemui.shared.recents.model.Task
|
||||
|
||||
@@ -53,14 +53,29 @@ class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: Attribu
|
||||
override fun computeTaskCornerRadius(context: Context) =
|
||||
computeWindowCornerRadius(context)
|
||||
}
|
||||
|
||||
private val taskThumbnailViewDeprecatedPool =
|
||||
ViewPool<TaskThumbnailViewDeprecated>(
|
||||
context,
|
||||
this,
|
||||
R.layout.task_thumbnail_deprecated,
|
||||
VIEW_POOL_MAX_SIZE,
|
||||
VIEW_POOL_INITIAL_SIZE,
|
||||
)
|
||||
if (!enableRefactorTaskThumbnail()) {
|
||||
ViewPool<TaskThumbnailViewDeprecated>(
|
||||
context,
|
||||
this,
|
||||
R.layout.task_thumbnail_deprecated,
|
||||
VIEW_POOL_MAX_SIZE,
|
||||
VIEW_POOL_INITIAL_SIZE,
|
||||
)
|
||||
} else null
|
||||
|
||||
private val taskThumbnailViewPool =
|
||||
if (enableRefactorTaskThumbnail()) {
|
||||
ViewPool<TaskThumbnailView>(
|
||||
context,
|
||||
this,
|
||||
R.layout.task_thumbnail,
|
||||
VIEW_POOL_MAX_SIZE,
|
||||
VIEW_POOL_INITIAL_SIZE,
|
||||
)
|
||||
} else null
|
||||
|
||||
private val tempPointF = PointF()
|
||||
private val tempRect = Rect()
|
||||
private lateinit var backgroundView: View
|
||||
@@ -117,9 +132,9 @@ class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: Attribu
|
||||
tasks.map { task ->
|
||||
val snapshotView =
|
||||
if (enableRefactorTaskThumbnail()) {
|
||||
LayoutInflater.from(context).inflate(R.layout.task_thumbnail, this, false)
|
||||
taskThumbnailViewPool!!.view
|
||||
} else {
|
||||
taskThumbnailViewDeprecatedPool.view
|
||||
taskThumbnailViewDeprecatedPool!!.view
|
||||
}
|
||||
|
||||
addView(
|
||||
@@ -148,9 +163,11 @@ class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: Attribu
|
||||
super.onRecycle()
|
||||
visibility = VISIBLE
|
||||
taskContainers.forEach {
|
||||
if (!enableRefactorTaskThumbnail()) {
|
||||
removeView(it.thumbnailViewDeprecated)
|
||||
taskThumbnailViewDeprecatedPool.recycle(it.thumbnailViewDeprecated)
|
||||
removeView(it.snapshotView)
|
||||
if (enableRefactorTaskThumbnail()) {
|
||||
taskThumbnailViewPool!!.recycle(it.thumbnailView)
|
||||
} else {
|
||||
taskThumbnailViewDeprecatedPool!!.recycle(it.thumbnailViewDeprecated)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -299,7 +316,7 @@ class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: Attribu
|
||||
companion object {
|
||||
private const val TAG = "DesktopTaskView"
|
||||
private const val DEBUG = false
|
||||
private const val VIEW_POOL_MAX_SIZE = 10
|
||||
private const val VIEW_POOL_MAX_SIZE = 5
|
||||
|
||||
// As DesktopTaskView is inflated in background, use initialSize=0 to avoid initPool.
|
||||
private const val VIEW_POOL_INITIAL_SIZE = 0
|
||||
|
||||
@@ -157,12 +157,13 @@ class TaskContainer(
|
||||
|
||||
fun destroy() {
|
||||
digitalWellBeingToast?.destroy()
|
||||
if (enableRefactorTaskThumbnail()) {
|
||||
taskView.removeView(thumbnailView)
|
||||
}
|
||||
snapshotView.scaleX = 1f
|
||||
snapshotView.scaleY = 1f
|
||||
overlay.destroy()
|
||||
if (enableRefactorTaskThumbnail()) {
|
||||
RecentsDependencies.getInstance().removeScope(snapshotView)
|
||||
RecentsDependencies.getInstance().removeScope(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun bindThumbnailView() {
|
||||
|
||||
@@ -82,6 +82,7 @@ import com.android.quickstep.TaskViewUtils
|
||||
import com.android.quickstep.orientation.RecentsPagedOrientationHandler
|
||||
import com.android.quickstep.recents.di.RecentsDependencies
|
||||
import com.android.quickstep.recents.di.get
|
||||
import com.android.quickstep.task.thumbnail.TaskThumbnailView
|
||||
import com.android.quickstep.task.viewmodel.TaskViewModel
|
||||
import com.android.quickstep.util.ActiveGestureErrorDetector
|
||||
import com.android.quickstep.util.ActiveGestureLog
|
||||
@@ -723,20 +724,23 @@ constructor(
|
||||
@StagePosition stagePosition: Int,
|
||||
taskOverlayFactory: TaskOverlayFactory,
|
||||
): TaskContainer {
|
||||
val thumbnailViewDeprecated: TaskThumbnailViewDeprecated = findViewById(thumbnailViewId)!!
|
||||
val existingThumbnailView: View = findViewById(thumbnailViewId)!!
|
||||
val snapshotView =
|
||||
if (enableRefactorTaskThumbnail()) {
|
||||
thumbnailViewDeprecated.visibility = GONE
|
||||
val indexOfSnapshotView = indexOfChild(thumbnailViewDeprecated)
|
||||
LayoutInflater.from(context).inflate(R.layout.task_thumbnail, this, false).also {
|
||||
it.id = thumbnailViewId
|
||||
addView(it, indexOfSnapshotView, thumbnailViewDeprecated.layoutParams)
|
||||
when {
|
||||
!enableRefactorTaskThumbnail() -> existingThumbnailView
|
||||
existingThumbnailView is TaskThumbnailView -> existingThumbnailView
|
||||
else -> {
|
||||
val indexOfSnapshotView = indexOfChild(existingThumbnailView)
|
||||
LayoutInflater.from(context)
|
||||
.inflate(R.layout.task_thumbnail, this, false)
|
||||
.also {
|
||||
it.id = thumbnailViewId
|
||||
addView(it, indexOfSnapshotView, existingThumbnailView.layoutParams)
|
||||
removeView(existingThumbnailView)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
thumbnailViewDeprecated
|
||||
}
|
||||
val iconView = getOrInflateIconView(iconViewId)
|
||||
val digitalWellBeingToast = findViewById<DigitalWellBeingToast>(digitalWellbeingBannerId)!!
|
||||
return TaskContainer(
|
||||
this,
|
||||
task,
|
||||
@@ -744,7 +748,7 @@ constructor(
|
||||
iconView,
|
||||
TransformingTouchDelegate(iconView.asView()),
|
||||
stagePosition,
|
||||
digitalWellBeingToast,
|
||||
findViewById(digitalWellbeingBannerId)!!,
|
||||
findViewById(showWindowViewId)!!,
|
||||
taskOverlayFactory,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user