Android 如何优化setTint

Android 如何优化setTint,android,xml,kotlin,optimization,android-databinding,Android,Xml,Kotlin,Optimization,Android Databinding,我正在制作一级方程式赛车灯光系统。因此,我创建了一个带有颜色#212121的圆形网格。当我尝试更改颜色时,会出现以下错误: 2021-02-17 09:41:25.186 29905-29905/com.example.ligthsouttimer I/Choreographer: Skipped 241 frames! The application may be doing too much work on its main thread. 当我只改变一个圆圈时,没有问题,但现在它不断跳

我正在制作一级方程式赛车灯光系统。因此,我创建了一个带有颜色#212121的圆形网格。当我尝试更改颜色时,会出现以下错误:

2021-02-17 09:41:25.186 29905-29905/com.example.ligthsouttimer I/Choreographer: Skipped 241 frames!  The application may be doing too much work on its main thread.
当我只改变一个圆圈时,没有问题,但现在它不断跳过所有发生事情的帧。
我正在用我的手机(三星galaxy A40)运行。


我的xml布局文件:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginStart="25dp"
            android:layout_marginTop="50dp"
            android:layout_marginEnd="25dp"
            android:layout_marginBottom="50dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintDimensionRatio="h,3:2"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/blk_rectangle" />

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:orientation="vertical"
            android:padding="5dp"
            app:layout_constraintBottom_toBottomOf="@+id/imageView"
            app:layout_constraintEnd_toEndOf="@+id/imageView"
            app:layout_constraintStart_toStartOf="@+id/imageView"
            app:layout_constraintTop_toTopOf="@+id/imageView">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:orientation="horizontal">

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle11"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle21"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle31"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle41"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle51"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:orientation="horizontal">

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle12"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle22"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle32"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle42"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle52"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:orientation="horizontal">

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle13"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle23"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle33"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle43"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle53"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:orientation="horizontal">

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle14"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle24"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle34"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle44"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <ImageView
                        android:id="@+id/circle54"
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:padding="5dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintDimensionRatio="w,1:1"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent"
                        app:srcCompat="@drawable/circle" />
                </androidx.constraintlayout.widget.ConstraintLayout>

            </LinearLayout>

        </LinearLayout>

        <Button
            android:id="@+id/start_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/imageView" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

首先,可以通过扁平化结构来优化xml布局。应该可以将所有图像视图放置在单个ConstraintLayout内,并删除中间线性布局和ConstraintLayout。
这将使视图膨胀和布局传递速度大大加快


尽管如此,实际问题是:

        var random_sleep = (2..3000).random().toLong()
        Thread.sleep(random_sleep)
调用
Thead.sleep
会阻塞线程,这意味着在时间结束之前它无法执行任何其他操作。此代码在主线程上执行,因此整个应用程序在睡眠时被冻结且无响应,因此出现“应用程序可能在其主线程上做了太多工作”消息


安排一些代码稍后运行最容易在Android中完成。例如:

val delay = (2..3000).random().toLong()
Handler(Looper.getMainLooper()).postDelayed({
    // code to run after delay
}, delay)

删除
线程.sleep
调用并将所有要延迟的
setTint
调用放在该函数中,应该可以解决阻塞问题。

首先,可以通过展平结构优化xml布局。应该可以将所有图像视图放置在单个ConstraintLayout内,并删除中间线性布局和ConstraintLayout。
这将使视图膨胀和布局传递速度大大加快


尽管如此,实际问题是:

        var random_sleep = (2..3000).random().toLong()
        Thread.sleep(random_sleep)
调用
Thead.sleep
会阻塞线程,这意味着在时间结束之前它无法执行任何其他操作。此代码在主线程上执行,因此整个应用程序在睡眠时被冻结且无响应,因此出现“应用程序可能在其主线程上做了太多工作”消息


安排一些代码稍后运行最容易在Android中完成。例如:

val delay = (2..3000).random().toLong()
Handler(Looper.getMainLooper()).postDelayed({
    // code to run after delay
}, delay)

删除
线程.sleep
调用并将所有要延迟的
setTint
调用放在该函数中应该可以解决阻塞问题。

@Robco的答案是,当您使用
Kotlin
时,您可以利用
协程
,尤其是在这种情况下。
Handler
的问题是,您需要用延迟嵌套所有后续调用,而且没有适当的取消策略,这可能会导致崩溃。如果我必须根据您的代码执行总延迟(例如
7
秒)的操作,我更喜欢使用协同路由的方式

val tintJob = Job() // you can cancel it in onDestroy
binding.startBtn.setOnClickListener {
    tintJob = CoroutineScope(Dispatchers.Main).launch {
        applyRedTintFor13_14()
        delay(1_000)
        applyRedTintFor23_24()
        delay(1_000)
        applyRedTintFor33_34()
        delay(1_000)
        applyRedTintFor43_44()
        delay(1_000)
        applyRedTintFor53_54()
        delay(1_000)
        delay((2..3000).random().toLong())
        applyGreyTintToAll()
   }
}

如果您使用的是
coroutine android extensions
,则可以直接使用
lifecyclescope
,当状态为非活动状态时,它将自行销毁

binding.startBtn.setOnClickListener {
   lifeCycleScope.launch {
        applyRedTintFor13_14()
        delay(1_000)
        applyRedTintFor23_24()
        delay(1_000)
        applyRedTintFor33_34()
        delay(1_000)
        applyRedTintFor43_44()
        delay(1_000)
        applyRedTintFor53_54()
        delay(1_000)
        delay((2..3000).random().toLong())
        applyGreyTintToAll()
   }
}

@Robco的回答是:当您使用
Kotlin
时,您可以利用
协同程序
,尤其是在这种情况下。
Handler
的问题是,您需要用延迟嵌套所有后续调用,而且没有适当的取消策略,这可能会导致崩溃。如果我必须根据您的代码执行总延迟(例如
7
秒)的操作,我更喜欢使用协同路由的方式

val tintJob = Job() // you can cancel it in onDestroy
binding.startBtn.setOnClickListener {
    tintJob = CoroutineScope(Dispatchers.Main).launch {
        applyRedTintFor13_14()
        delay(1_000)
        applyRedTintFor23_24()
        delay(1_000)
        applyRedTintFor33_34()
        delay(1_000)
        applyRedTintFor43_44()
        delay(1_000)
        applyRedTintFor53_54()
        delay(1_000)
        delay((2..3000).random().toLong())
        applyGreyTintToAll()
   }
}

如果您使用的是
coroutine android extensions
,则可以直接使用
lifecyclescope
,当状态为非活动状态时,它将自行销毁

binding.startBtn.setOnClickListener {
   lifeCycleScope.launch {
        applyRedTintFor13_14()
        delay(1_000)
        applyRedTintFor23_24()
        delay(1_000)
        applyRedTintFor33_34()
        delay(1_000)
        applyRedTintFor43_44()
        delay(1_000)
        applyRedTintFor53_54()
        delay(1_000)
        delay((2..3000).random().toLong())
        applyGreyTintToAll()
   }
}

每个带有“apply”的句子都给出了未解决的错误引用。它还给出了一个错误,当按下alt+enter键时,会将“as CompletableJob”放在作业后面。我不知道这是否有什么区别。每一个带有“apply”的句子都给出了未解决的错误引用。它还给出了一个错误,当按下alt+enter键时,会将“as CompletableJob”放在作业后面。我不知道这是否有什么不同。