项目结构

HighPerformanceViewDemo/
├── app/
│   ├── src/main/java/com/example/performance/
│   │   ├── MainActivity.kt
│   │   ├── view/
│   │   │   ├── BadProgressView.kt
│   │   │   ├── OptimizedProgressView.kt
│   │   │   ├── AsyncProgressView.kt
│   │   │   └── HighPerformanceProgressView.kt
│   │   ├── utils/
│   │   │   ├── PerformanceMonitor.kt
│   │   │   ├── BitmapManager.kt
│   │   │   └── FrameRateTracker.kt
│   │   └── performance/
│   │       ├── BenchmarkActivity.kt
│   │       └── PerformancePanel.kt
│   └── build.gradle.kts
└── README.md

1. 主界面实现 (MainActivity.kt)

package com.example.performance

import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.SeekBar
import androidx.appcompat.app.AppCompatActivity
import com.example.performance.databinding.ActivityMainBinding
import com.example.performance.utils.PerformanceMonitor
import com.example.performance.view.*

class MainActivity : AppCompatActivity() {
    
    private lateinit var binding: ActivityMainBinding
    private val handler = Handler(Looper.getMainLooper())
    private var isRunning = false
    private var currentProgress = 0f
    private val progressUpdater = object : Runnable {
        override fun run() {
            if (isRunning) {
                currentProgress = (currentProgress + 0.01f) % 1f
                
                binding.badProgressView.setProgress(currentProgress)
                binding.optimizedProgressView.setProgress(currentProgress)
                binding.asyncProgressView.setProgress(currentProgress)
                binding.highPerformanceProgressView.setProgress(currentProgress)
                
                handler.postDelayed(this, 16) // ~60fps更新
            }
        }
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        setupViews()
        setupPerformanceMonitor()
    }
    
    private fun setupViews() {
        // 手动进度控制
        binding.seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
                val progressFloat = progress / 100f
                binding.badProgressView.setProgress(progressFloat)
                binding.optimizedProgressView.setProgress(progressFloat)
                binding.asyncProgressView.setProgress(progressFloat)
                binding.highPerformanceProgressView.setProgress(progressFloat)
            }
            
            override fun onStartTrackingTouch(seekBar: SeekBar) {}
            override fun onStopTrackingTouch(seekBar: SeekBar) {}
        })
        
        // 自动动画开关
        binding.btnToggleAnimation.setOnClickListener {
            isRunning = !isRunning
            binding.btnToggleAnimation.text = if (isRunning) "停止动画" else "开始动画"
            
            if (isRunning) {
                handler.post(progressUpdater)
            } else {
                handler.removeCallbacks(progressUpdater)
            }
        }
        
        // 性能测试按钮
        binding.btnBenchmark.setOnClickListener {
            BenchmarkActivity.start(this)
        }
        
        // 清空缓存按钮
        binding.btnClearCache.setOnClickListener {
            BitmapManager.clearCache()
            binding.tvCacheStatus.text = "缓存已清空"
            handler.postDelayed({
                binding.tvCacheStatus.text = ""
            }, 1500)
        }
    }
    
    private fun setupPerformanceMonitor() {
        PerformanceMonitor.startMonitoring(this)
        
        // 每2秒更新一次性能数据
        handler.post(object : Runnable {
            override fun run() {
                val info = PerformanceMonitor.getPerformanceInfo()
                
                binding.tvFps.text = String.format("FPS: %.1f", info.fps)
                binding.tvMemory.text = String.format("内存: %.1fMB", info.usedMemoryMB)
                binding.tvCpu.text = String.format("CPU: %.1f%%", info.cpuUsage)
                binding.tvGpuTime.text = String.format("GPU: %.1fms", info.gpuTimeMs)
                
                // 设置颜色提示
                val fpsColor = when {
                    info.fps > 55 -> 0xFF4CAF50.toInt()  // 绿色
                    info.fps > 30 -> 0xFFFFC107.toInt()  // 黄色
                    else -> 0xFFF44336.toInt()            // 红色
                }
                binding.tvFps.setTextColor(fpsColor)
                
                handler.postDelayed(this, 2000)
            }
        })
    }
    
    override fun onDestroy() {
        super.onDestroy()
        isRunning = false
        handler.removeCallbacks(progressUpdater)
        PerformanceMonitor.stopMonitoring()
    }
}

2. 布局文件 (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <!-- 性能监控面板 -->
        <com.example.performance.performance.PerformancePanel
            android:id="@+id/performancePanel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="24dp" />

        <!-- 控制面板 -->
        <androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="24dp"
            app:cardCornerRadius="8dp"
            app:cardElevation="4dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:padding="16dp">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="控制面板"
                    android:textSize="18sp"
                    android:textStyle="bold"
                    android:layout_marginBottom="16dp" />

                <SeekBar
                    android:id="@+id/seekBar"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="16dp" />

                <Button
                    android:id="@+id/btnToggleAnimation"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="开始动画"
                    android:layout_marginBottom="8dp" />

                <Button
                    android:id="@+id/btnBenchmark"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="性能测试"
                    android:layout_marginBottom="8dp" />

                <Button
                    android:id="@+id/btnClearCache"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="清空Bitmap缓存" />

                <TextView
                    android:id="@+id/tvCacheStatus"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="@android:color/holo_green_dark"
                    android:layout_marginTop="8dp" />
            </LinearLayout>
        </androidx.cardview.widget.CardView>

        <!-- 四个对比View -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="❌ 基础实现 (问题版)"
            android:textSize="16sp"
            android:textStyle="bold"
            android:layout_marginBottom="8dp" />

        <com.example.performance.view.BadProgressView
            android:id="@+id/badProgressView"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_marginBottom="24dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="✅ 优化版1:硬件加速"
            android:textSize="16sp"
            android:textStyle="bold"
            android:layout_marginBottom="8dp" />

        <com.example.performance.view.OptimizedProgressView
            android:id="@+id/optimizedProgressView"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_marginBottom="24dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="🚀 优化版2:异步绘制 (API 28+)"
            android:textSize="16sp"
            android:textStyle="bold"
            android:layout_marginBottom="8dp" />

        <com.example.performance.view.AsyncProgressView
            android:id="@+id/asyncProgressView"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_marginBottom="24dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="🏆 优化版3:综合优化"
            android:textSize="16sp"
            android:textStyle="bold"
            android:layout_marginBottom="8dp" />

        <com.example.performance.view.HighPerformanceProgressView
            android:id="@+id/highPerformanceProgressView"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_marginBottom="24dp" />

        <!-- 实时性能数据 -->
        <androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:cardCornerRadius="8dp"
            app:cardElevation="4dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:padding="16dp">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="实时性能数据"
                    android:textSize="18sp"
                    android:textStyle="bold"
                    android:layout_marginBottom="16dp" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal"
                    android:layout_marginBottom="8dp">

                    <TextView
                        android:id="@+id/tvFps"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="FPS: --"
                        android:textSize="14sp" />

                    <TextView
                        android:id="@+id/tvMemory"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="内存: --MB"
                        android:textSize="14sp" />
                </LinearLayout>

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                    <TextView
                        android:id="@+id/tvCpu"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="CPU: --%"
                        android:textSize="14sp" />

                    <TextView
                        android:id="@+id/tvGpuTime"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="GPU: --ms"
                        android:textSize="14sp" />
                </LinearLayout>
            </LinearLayout>
        </androidx.cardview.widget.CardView>
    </LinearLayout>
</ScrollView>

3. 四个View的完整实现

3.1 BadProgressView.kt (问题版)

package com.example.performance.view

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import kotlin.random.Random

class BadProgressView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    
    // ❌ 问题1:每次onDraw都创建新的Paint对象
    // ❌ 问题2:Shader在onDraw中频繁创建
    // ❌ 问题3:过度绘制
    // ❌ 问题4:对象分配频繁
    
    private var progress = 0f
    private var lastUpdateTime = 0L
    private var frameCount = 0
    
    init {
        // 故意不启用硬件加速,展示问题
        setLayerType(LAYER_TYPE_SOFTWARE, null)
    }
    
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        
        // ❌ 每帧都创建新对象
        val paint = Paint().apply {
            color = Color.RED
            style = Paint.Style.FILL
        }
        
        // ❌ 在onDraw中创建Shader
        val shader = LinearGradient(
            0f, 0f, width.toFloat(), 0f,
            Color.RED, Color.BLUE, Shader.TileMode.CLAMP
        )
        paint.shader = shader
        
        // ❌ 每帧都创建RectF
        val rect = RectF(0f, 0f, width * progress, height.toFloat())
        
        // 绘制背景
        canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), paint)
        
        // ❌ 过度绘制:先画背景再画进度
        paint.color = Color.GREEN
        canvas.drawRect(rect, paint)
        
        // ❌ 复杂绘制:圆角效果(软件绘制性能差)
        val path = Path().apply {
            addRoundRect(rect, 20f, 20f, Path.Direction.CW)
        }
        paint.color = Color.YELLOW
        canvas.drawPath(path, paint)
        
        // ❌ 文本绘制频繁
        val textPaint = Paint().apply {
            color = Color.WHITE
            textSize = 24f
            textAlign = Paint.Align.CENTER
        }
        
        // ❌ 每帧都计算文本位置
        val text = "${(progress * 100).toInt()}%"
        val textBounds = Rect()
        textPaint.getTextBounds(text, 0, text.length, textBounds)
        
        // ❌ 多次绘制文本
        canvas.drawText(text, width / 2f, height / 2f, textPaint)
        canvas.drawText("FPS: ${calculateFPS()}", 100f, 30f, textPaint)
        
        // ❌ 不必要的阴影效果
        paint.setShadowLayer(10f, 5f, 5f, Color.GRAY)
        canvas.drawText("性能差", 200f, 30f, paint)
        
        frameCount++
    }
    
    fun setProgress(progress: Float) {
        this.progress = progress
        invalidate() // ❌ 全量刷新
    }
    
    private fun calculateFPS(): Int {
        val currentTime = System.currentTimeMillis()
        if (currentTime - lastUpdateTime > 1000) {
            lastUpdateTime = currentTime
            val fps = frameCount
            frameCount = 0
            return fps
        }
        return 0
    }
    
    // ❌ 内存泄漏风险
    private val bitmaps = mutableListOf<Bitmap>()
    
    private fun createMemoryLeak() {
        // 故意创建Bitmap但不回收
        repeat(10) {
            bitmaps.add(
                Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)
            )
        }
    }
    
    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        // ❌ 忘记清理Bitmap
        // bitmaps.forEach { it.recycle() }
    }
}

3.2 OptimizedProgressView.kt (硬件加速优化版)

package com.example.performance.view

import android.content.Context
import android.graphics.*
import android.os.Build
import android.util.AttributeSet
import android.view.View
import androidx.annotation.RequiresApi

class OptimizedProgressView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    
    // ✅ 优化1:复用Paint对象
    private val progressPaint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.DITHER_FLAG).apply {
        style = Paint.Style.FILL
        color = Color.BLUE
    }
    
    private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.WHITE
        textSize = 32f
        textAlign = Paint.Align.CENTER
        typeface = Typeface.DEFAULT_BOLD
    }
    
    private val bgPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.LTGRAY
        style = Paint.Style.FILL
    }
    
    // ✅ 优化2:复用RectF对象
    private val progressRect = RectF()
    private val bgRect = RectF()
    
    // ✅ 优化3:Shader缓存
    private var gradientShader: LinearGradient? = null
    private var lastWidth = 0
    
    // ✅ 优化4:文本边界缓存
    private val textBounds = Rect()
    private var cachedText = ""
    
    private var progress = 0f
    
    init {
        // ✅ 启用硬件加速
        setLayerType(LAYER_TYPE_HARDWARE, null)
        
        // ✅ 标记不支持硬件加速的操作
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            forceHasOverlappingRendering(false)
        }
        
        // ✅ 初始化Shader
        updateShaderIfNeeded()
    }
    
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        updateShaderIfNeeded()
    }
    
    private fun updateShaderIfNeeded() {
        if (width != lastWidth && width > 0) {
            gradientShader = LinearGradient(
                0f, 0f, width.toFloat(), 0f,
                intArrayOf(
                    Color.parseColor("#FF6B6B"),
                    Color.parseColor("#4ECDC4"),
                    Color.parseColor("#45B7D1")
                ),
                floatArrayOf(0f, 0.5f, 1f),
                Shader.TileMode.CLAMP
            )
            progressPaint.shader = gradientShader
            lastWidth = width
        }
    }
    
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        
        // ✅ 检查硬件加速
        if (!canvas.isHardwareAccelerated) {
            drawSoftware(canvas)
            return
        }
        
        // ✅ 绘制背景
        bgRect.set(0f, 0f, width.toFloat(), height.toFloat())
        canvas.drawRoundRect(bgRect, 12f, 12f, bgPaint)
        
        // ✅ 绘制进度条
        if (progress > 0) {
            progressRect.set(0f, 0f, width * progress, height.toFloat())
            canvas.drawRoundRect(progressRect, 12f, 12f, progressPaint)
            
            // ✅ 缓存文本计算
            val text = "${(progress * 100).toInt()}%"
            if (text != cachedText) {
                textPaint.getTextBounds(text, 0, text.length, textBounds)
                cachedText = text
            }
            
            // ✅ 计算文本位置
            val x = (width * progress).coerceAtLeast(textBounds.width() / 2f + 20)
            val y = height / 2f - (textBounds.top + textBounds.bottom) / 2f
            
            // ✅ 只绘制一次文本
            canvas.drawText(text, x, y, textPaint)
        }
    }
    
    private fun drawSoftware(canvas: Canvas) {
        // 软件绘制的回退方案
        bgRect.set(0f, 0f, width.toFloat(), height.toFloat())
        canvas.drawRoundRect(bgRect, 12f, 12f, bgPaint)
        
        if (progress > 0) {
            progressRect.set(0f, 0f, width * progress, height.toFloat())
            canvas.drawRoundRect(progressRect, 12f, 12f, progressPaint)
        }
    }
    
    fun setProgress(progress: Float) {
        this.progress = progress.coerceIn(0f, 1f)
        
        // ✅ 使用局部刷新
        val left = (width * (this.progress - 0.01f)).toInt()
        val right = (width * (this.progress + 0.01f)).toInt()
        invalidate(left, 0, right, height)
    }
    
    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        // ✅ 清理资源
        gradientShader = null
    }
}

3.3 AsyncProgressView.kt (异步绘制版)

package com.example.performance.view

import android.content.Context
import android.graphics.*
import android.os.*
import android.util.AttributeSet
import android.view.View
import androidx.annotation.RequiresApi
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

@RequiresApi(Build.VERSION_CODES.P)
class AsyncProgressView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    
    // ✅ 异步绘制优化
    private val renderThread = RenderThread()
    private val mainHandler = Handler(Looper.getMainLooper())
    private val asyncExecutor: ExecutorService = Executors.newSingleThreadExecutor()
    
    // ✅ RenderNode API
    private var renderNode: RenderNode? = null
    private var currentBitmap: Bitmap? = null
    
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.FILL
    }
    
    private var progress = 0f
    private var targetProgress = 0f
    private val animator = ValueAnimator.ofFloat(0f, 1f).apply {
        duration = 300
        interpolator = android.view.animation.AccelerateDecelerateInterpolator()
        addUpdateListener {
            progress = it.animatedValue as Float
            scheduleRender()
        }
    }
    
    init {
        // ✅ 必须启用硬件加速
        setLayerType(LAYER_TYPE_HARDWARE, null)
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // ✅ 使用RenderNode
            renderNode = RenderNode("AsyncProgressView")
        }
        
        // ✅ 初始化渐变
        paint.shader = LinearGradient(
            0f, 0f, 1000f, 0f, // 使用最大宽度
            intArrayOf(
                Color.parseColor("#667EEA"),
                Color.parseColor("#764BA2"),
                Color.parseColor("#F093FB")
            ),
            null,
            Shader.TileMode.CLAMP
        )
    }
    
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        
        // ✅ 创建离屏Bitmap用于异步绘制
        if (w > 0 && h > 0) {
            currentBitmap?.recycle()
            currentBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
            renderNode?.setPosition(0, 0, w, h)
        }
    }
    
    fun setProgress(progress: Float) {
        targetProgress = progress.coerceIn(0f, 1f)
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // ✅ 使用RenderThread驱动的动画
            animator.setFloatValues(this.progress, targetProgress)
            if (!animator.isRunning) {
                animator.start()
            }
        } else {
            this.progress = targetProgress
            scheduleRender()
        }
    }
    
    private fun scheduleRender() {
        // ✅ 提交异步绘制任务
        asyncExecutor.submit {
            renderOffscreen()
            
            // ✅ 完成后通知主线程更新
            mainHandler.post {
                invalidate()
            }
        }
    }
    
    private fun renderOffscreen() {
        val bitmap = currentBitmap ?: return
        val canvas = Canvas(bitmap)
        
        // ✅ 在后台线程绘制
        drawContent(canvas)
        
        // ✅ 使用RenderNode记录绘制命令
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            val node = renderNode ?: return
            node.beginRecording().let { recorder ->
                drawContent(recorder)
                node.endRecording()
            }
        }
    }
    
    private fun drawContent(canvas: Canvas) {
        // 清空画布
        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
        
        // 绘制背景
        canvas.drawRoundRect(
            0f, 0f, width.toFloat(), height.toFloat(),
            16f, 16f, Paint().apply {
                color = Color.parseColor("#E0E0E0")
                isAntiAlias = true
            }
        )
        
        // 绘制进度
        val progressWidth = width * progress
        if (progressWidth > 0) {
            canvas.drawRoundRect(
                0f, 0f, progressWidth, height.toFloat(),
                16f, 16f, paint
            )
            
            // 绘制文本
            val text = "${(progress * 100).toInt()}%"
            val textPaint = Paint().apply {
                color = Color.WHITE
                textSize = 28f
                textAlign = Paint.Align.CENTER
                isAntiAlias = true
                typeface = Typeface.DEFAULT_BOLD
            }
            
            val x = (width * progress / 2).coerceAtLeast(50f)
            val y = height / 2f - (textPaint.descent() + textPaint.ascent()) / 2
            
            canvas.drawText(text, x, y, textPaint)
        }
    }
    
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        
        if (!canvas.isHardwareAccelerated) {
            // 软件渲染回退
            drawContent(canvas)
            return
        }
        
        // ✅ 绘制预渲染的内容
        currentBitmap?.let { bitmap ->
            canvas.drawBitmap(bitmap, 0f, 0f, null)
        }
        
        // ✅ 使用RenderNode绘制
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            renderNode?.let { node ->
                canvas.drawRenderNode(node)
            }
        }
    }
    
    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        
        // ✅ 清理资源
        animator.cancel()
        asyncExecutor.shutdown()
        currentBitmap?.recycle()
        renderNode = null
        
        // ✅ 停止渲染线程
        renderThread.quit()
    }
    
    @RequiresApi(Build.VERSION_CODES.P)
    private inner class RenderThread : HandlerThread("RenderThread") {
        private lateinit var handler: Handler
        
        init {
            start()
            handler = Handler(looper)
        }
        
        fun render(frame: Long, callback: Runnable) {
            handler.postAtTime(callback, frame)
        }
        
        fun quit() {
            looper.quitSafely()
        }
    }
}

3.4 HighPerformanceProgressView.kt (综合优化版)

package com.example.performance.view

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.os.*
import android.util.AttributeSet
import android.view.Choreographer
import android.view.View
import androidx.annotation.RequiresApi
import com.example.performance.utils.BitmapManager
import kotlin.math.max
import kotlin.math.min

class HighPerformanceProgressView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr), Choreographer.FrameCallback {
    
    // ========== 优化配置 ==========
    companion object {
        // ✅ 静态Paint对象,避免重复创建
        private val PROGRESS_PAINT = Paint().apply {
            flags = Paint.ANTI_ALIAS_FLAG or Paint.DITHER_FLAG or Paint.FILTER_BITMAP_FLAG
            style = Paint.Style.FILL
            color = Color.parseColor("#2196F3")
        }
        
        private val TEXT_PAINT = Paint().apply {
            flags = Paint.ANTI_ALIAS_FLAG or Paint.SUBPIXEL_TEXT_FLAG
            color = Color.WHITE
            textSize = 36f
            textAlign = Paint.Align.CENTER
            typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL)
        }
        
        private val BG_PAINT = Paint().apply {
            flags = Paint.ANTI_ALIAS_FLAG
            color = Color.parseColor("#F5F5F5")
            style = Paint.Style.FILL
        }
        
        private val BORDER_PAINT = Paint().apply {
            flags = Paint.ANTI_ALIAS_FLAG
            color = Color.parseColor("#E0E0E0")
            style = Paint.Style.STROKE
            strokeWidth = 2f
        }
    }
    
    // ========== 状态管理 ==========
    private var currentProgress = 0f
    private var animatedProgress = 0f
    private var targetProgress = 0f
    private var isAnimating = false
    
    // ========== 对象复用池 ==========
    private val rectPool = mutableListOf<RectF>()
    private val pathPool = mutableListOf<Path>()
    
    private fun obtainRectF(): RectF {
        return if (rectPool.isNotEmpty()) {
            rectPool.removeAt(0).also { it.setEmpty() }
        } else {
            RectF()
        }
    }
    
    private fun recycleRectF(rect: RectF) {
        if (rectPool.size < 5) { // 限制池大小
            rectPool.add(rect)
        }
    }
    
    // ========== 缓存管理 ==========
    private var cachedWidth = 0
    private var cachedHeight = 0
    private var gradientShader: LinearGradient? = null
    private var lastShaderUpdateTime = 0L
    
    // ========== 路径预计算 ==========
    private val cornerPath = Path()
    private val clipPath = Path()
    private var pathsDirty = true
    
    // ========== 文本缓存 ==========
    private val textBounds = Rect()
    private var cachedText = ""
    private var cachedTextWidth = 0f
    
    // ========== 动画系统 ==========
    private val animator = ValueAnimator().apply {
        duration = 250L
        interpolator = android.view.animation.AccelerateDecelerateInterpolator()
        addUpdateListener {
            animatedProgress = it.animatedValue as Float
            if (useChoreographerSync) {
                scheduleFrame() // 使用Choreographer同步
            } else {
                invalidateOptimized()
            }
        }
    }
    
    // ========== 高刷新率适配 ==========
    private var refreshRate = 60f
    private var useChoreographerSync = false
    private var choreographer: Choreographer? = null
    private var vsyncTime = 0L
    
    // ========== 初始化 ==========
    init {
        // ✅ 启用硬件加速层
        setLayerType(LAYER_TYPE_HARDWARE, null)
        
        // ✅ 获取设备刷新率
        val display = context.getSystemService(Context.DISPLAY_SERVICE) as? android.view.Display
        refreshRate = display?.refreshRate ?: 60f
        
        // ✅ 根据刷新率调整动画时长
        if (refreshRate > 60) {
            useChoreographerSync = true
            choreographer = Choreographer.getInstance()
            animator.duration = (1000 * 60f / refreshRate).toLong()
        }
        
        // ✅ 标记无重叠渲染
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            forceHasOverlappingRendering(false)
        }
        
        // ✅ 禁用默认的clipChildren
        clipChildren = false
        
        // ✅ 初始化渐变
        updateGradientShader()
    }
    
    // ========== 尺寸处理 ==========
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        
        if (w != cachedWidth || h != cachedHeight) {
            cachedWidth = w
            cachedHeight = h
            pathsDirty = true
            updateGradientShader()
        }
    }
    
    private fun updateGradientShader() {
        if (cachedWidth <= 0) return
        
        val now = System.currentTimeMillis()
        // ✅ 限制Shader更新频率(至少间隔500ms)
        if (now - lastShaderUpdateTime > 500) {
            gradientShader = LinearGradient(
                0f, 0f, cachedWidth.toFloat(), 0f,
                intArrayOf(
                    Color.parseColor("#FF6B6B"),
                    Color.parseColor("#FFD166"),
                    Color.parseColor("#06D6A0"),
                    Color.parseColor("#118AB2")
                ),
                floatArrayOf(0f, 0.3f, 0.6f, 1f),
                Shader.TileMode.CLAMP
            ).apply {
                setLocalMatrix(Matrix().apply {
                    setScale(1.5f, 1f) // 扩大渐变范围,避免动画时重复创建
                })
            }
            
            PROGRESS_PAINT.shader = gradientShader
            lastShaderUpdateTime = now
        }
    }
    
    // ========== 绘制优化 ==========
    override fun onDraw(canvas: Canvas) {
        if (!canvas.isHardwareAccelerated) {
            drawSoftwareFallback(canvas)
            return
        }
        
        // ✅ 1. 预计算路径(惰性计算)
        if (pathsDirty) {
            updatePaths()
            pathsDirty = false
        }
        
        // ✅ 2. 使用离屏缓存(针对复杂效果)
        if (shouldUseOffscreenCache()) {
            drawWithOffscreenCache(canvas)
            return
        }
        
        // ✅ 3. 直接硬件加速绘制
        drawHardwareAccelerated(canvas)
    }
    
    private fun updatePaths() {
        cornerPath.reset()
        clipPath.reset()
        
        val cornerRadius = min(cachedHeight / 2f, 24f)
        
        // 圆角路径
        cornerPath.addRoundRect(
            0f, 0f, cachedWidth.toFloat(), cachedHeight.toFloat(),
            cornerRadius, cornerRadius, Path.Direction.CW
        )
        
        // 裁剪路径(用于进度条)
        clipPath.addRect(0f, 0f, cachedWidth.toFloat(), cachedHeight.toFloat(), Path.Direction.CW)
    }
    
    private fun shouldUseOffscreenCache(): Boolean {
        // 在需要复杂混合效果时使用离屏缓存
        return PROGRESS_PAINT.xfermode != null || 
               Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP
    }
    
    private fun drawWithOffscreenCache(canvas: Canvas) {
        // 使用BitmapManager获取缓存Bitmap
        val bitmap = BitmapManager.getOrCreateBitmap(
            "progress_cache_${cachedWidth}x${cachedHeight}",
            cachedWidth, cachedHeight
        )
        
        val offscreenCanvas = Canvas(bitmap)
        
        // 绘制到离屏Bitmap
        drawToCanvas(offscreenCanvas)
        
        // 绘制到实际Canvas
        canvas.drawBitmap(bitmap, 0f, 0f, null)
    }
    
    private fun drawHardwareAccelerated(canvas: Canvas) {
        // ✅ 保存画布状态
        canvas.save()
        
        // ✅ 使用clipPath避免过度绘制
        canvas.clipPath(cornerPath)
        
        // ✅ 绘制背景
        canvas.drawRoundRect(
            0f, 0f, cachedWidth.toFloat(), cachedHeight.toFloat(),
            12f, 12f, BG_PAINT
        )
        
        // ✅ 绘制边框
        canvas.drawRoundRect(
            0f, 0f, cachedWidth.toFloat(), cachedHeight.toFloat(),
            12f, 12f, BORDER_PAINT
        )
        
        // ✅ 绘制进度条
        if (animatedProgress > 0.001f) {
            val progressWidth = cachedWidth * animatedProgress
            
            // 使用对象池获取RectF
            val progressRect = obtainRectF().apply {
                set(0f, 0f, progressWidth, cachedHeight.toFloat())
            }
            
            canvas.drawRoundRect(progressRect, 12f, 12f, PROGRESS_PAINT)
            
            // ✅ 绘制文本(带缓存)
            drawOptimizedText(canvas, progressWidth)
            
            // 归还对象到池中
            recycleRectF(progressRect)
        }
        
        canvas.restore()
    }
    
    private fun drawOptimizedText(canvas: Canvas, progressWidth: Float) {
        val text = "${(animatedProgress * 100).toInt()}%"
        
        // ✅ 文本缓存优化
        if (text != cachedText) {
            TEXT_PAINT.getTextBounds(text, 0, text.length, textBounds)
            cachedText = text
            cachedTextWidth = TEXT_PAINT.measureText(text)
        }
        
        // ✅ 计算文本位置
        val textX = max(progressWidth / 2, cachedTextWidth / 2 + 16)
        val textY = cachedHeight / 2f - (textBounds.top + textBounds.bottom) / 2f
        
        // ✅ 文本阴影效果(硬件加速友好)
        if (progressWidth > cachedTextWidth + 32) {
            // 只在有足够空间时绘制阴影
            TEXT_PAINT.setShadowLayer(4f, 2f, 2f, Color.parseColor("#66000000"))
            canvas.drawText(text, textX, textY, TEXT_PAINT)
            TEXT_PAINT.clearShadowLayer()
        } else {
            canvas.drawText(text, textX, textY, TEXT_PAINT)
        }
    }
    
    private fun drawSoftwareFallback(canvas: Canvas) {
        // 软件渲染的简单实现
        canvas.drawRoundRect(
            0f, 0f, cachedWidth.toFloat(), cachedHeight.toFloat(),
            12f, 12f, BG_PAINT
        )
        
        if (animatedProgress > 0) {
            canvas.drawRoundRect(
                0f, 0f, cachedWidth * animatedProgress, cachedHeight.toFloat(),
                12f, 12f, PROGRESS_PAINT
            )
        }
    }
    
    private fun drawToCanvas(canvas: Canvas) {
        // 通用的绘制逻辑
        drawHardwareAccelerated(canvas)
    }
    
    // ========== 动画控制 ==========
    fun setProgress(progress: Float, animate: Boolean = true) {
        targetProgress = progress.coerceIn(0f, 1f)
        
        if (!animate || !useChoreographerSync) {
            currentProgress = targetProgress
            animatedProgress = targetProgress
            invalidateOptimized()
            return
        }
        
        if (isAnimating) {
            animator.cancel()
        }
        
        animator.setFloatValues(animatedProgress, targetProgress)
        animator.start()
        isAnimating = true
    }
    
    // ========== 高刷新率同步 ==========
    private fun scheduleFrame() {
        choreographer?.postFrameCallback(this)
    }
    
    override fun doFrame(frameTimeNanos: Long) {
        val frameTimeMillis = frameTimeNanos / 1_000_000
        
        // ✅ 基于垂直同步的时间差计算
        val delta = (frameTimeMillis - vsyncTime).coerceAtLeast(16L)
        vsyncTime = frameTimeMillis
        
        // ✅ 更新动画进度(基于时间插值)
        if (isAnimating) {
            val fraction = animator.animatedFraction
            animatedProgress = currentProgress + (targetProgress - currentProgress) * fraction
            
            if (fraction >= 1f) {
                isAnimating = false
                currentProgress = targetProgress
                choreographer?.removeFrameCallback(this)
            } else {
                choreographer?.postFrameCallback(this)
            }
            
            invalidateOptimized()
        }
    }
    
    // ========== 刷新优化 ==========
    private fun invalidateOptimized() {
        // ✅ 计算脏矩形,只刷新需要更新的区域
        val progressWidth = cachedWidth * animatedProgress
        val dirtyLeft = (progressWidth - 50).toInt().coerceAtLeast(0)
        val dirtyRight = (progressWidth + 50).toInt().coerceAtMost(cachedWidth)
        
        invalidate(dirtyLeft, 0, dirtyRight, cachedHeight)
    }
    
    // ========== 内存管理 ==========
    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        
        // ✅ 停止所有动画
        animator.cancel()
        choreographer?.removeFrameCallback(this)
        
        // ✅ 清理渐变
        gradientShader = null
        PROGRESS_PAINT.shader = null
        
        // ✅ 清理对象池
        rectPool.clear()
        pathPool.clear()
        
        // ✅ 通知BitmapManager清理相关缓存
        BitmapManager.removeCache("progress_cache_${cachedWidth}x${cachedHeight}")
    }
    
    // ========== 性能监控 ==========
    private var drawStartTime = 0L
    
    override fun dispatchDraw(canvas: Canvas?) {
        drawStartTime = System.nanoTime()
        super.dispatchDraw(canvas)
        val drawTime = (System.nanoTime() - drawStartTime) / 1_000_000f
        
        // 监控绘制时间(生产环境应该移除)
        if (drawTime > 16) {
            // 绘制时间过长警告
            android.util.Log.w("Performance", "HighPerformanceProgressView draw time: ${drawTime}ms")
        }
    }
}

4. 性能监控工具

4.1 PerformanceMonitor.kt

package com.example.performance.utils

import android.app.Activity
import android.app.ActivityManager
import android.content.Context
import android.os.Build
import android.os.Debug
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.Choreographer
import kotlin.math.roundToInt

data class PerformanceInfo(
    val fps: Float,
    val usedMemoryMB: Float,
    val totalMemoryMB: Float,
    val cpuUsage: Float,
    val gpuTimeMs: Float,
    val jankCount: Int,
    val frameTime95th: Float
)

object PerformanceMonitor : Choreographer.FrameCallback {
    
    private var isMonitoring = false
    private var frameCount = 0
    private var lastFrameTime = 0L
    private var frameTimes = mutableListOf<Long>()
    private val handler = Handler(Looper.getMainLooper())
    private var activity: Activity? = null
    private var jankThreshold = 16666667L // 16.67ms in nanoseconds
    private var jankCount = 0
    private val frameTimeHistory = ArrayDeque<Long>()
    private const val HISTORY_SIZE = 240 // 4秒数据(按60fps)
    
    // 性能数据回调
    var onPerformanceUpdate: ((PerformanceInfo) -> Unit)? = null
    
    fun startMonitoring(activity: Activity) {
        if (isMonitoring) return
        
        this.activity = activity
        isMonitoring = true
        frameCount = 0
        lastFrameTime = System.nanoTime()
        frameTimes.clear()
        frameTimeHistory.clear()
        jankCount = 0
        
        // 根据刷新率调整阈值
        val display = activity.getSystemService(Context.DISPLAY_SERVICE) 
            as android.view.Display
        val refreshRate = display.refreshRate
        jankThreshold = (1_000_000_000L / refreshRate).toLong()
        
        // 开始监控
        Choreographer.getInstance().postFrameCallback(this)
        
        Log.i("PerformanceMonitor", "Started monitoring with refresh rate: ${refreshRate}Hz")
    }
    
    fun stopMonitoring() {
        isMonitoring = false
        Choreographer.getInstance().removeFrameCallback(this)
        activity = null
        Log.i("PerformanceMonitor", "Stopped monitoring")
    }
    
    override fun doFrame(frameTimeNanos: Long) {
        if (!isMonitoring) return
        
        // 计算帧时间
        val frameTime = frameTimeNanos - lastFrameTime
        lastFrameTime = frameTimeNanos
        
        // 记录帧时间
        frameTimes.add(frameTime)
        frameTimeHistory.addLast(frameTime)
        if (frameTimeHistory.size > HISTORY_SIZE) {
            frameTimeHistory.removeFirst()
        }
        
        // 检测卡顿
        if (frameTime > jankThreshold * 2) {
            jankCount++
            Log.w("PerformanceMonitor", "Jank detected: ${frameTime / 1_000_000}ms")
        }
        
        frameCount++
        
        // 每秒计算一次FPS
        if (frameCount >= 60) { // 大约每秒(按60fps)
            calculatePerformance()
            frameCount = 0
            frameTimes.clear()
        }
        
        // 继续监控下一帧
        Choreographer.getInstance().postFrameCallback(this)
    }
    
    private fun calculatePerformance() {
        val ctx = activity ?: return
        
        // 计算FPS
        val fps = if (frameTimes.isNotEmpty()) {
            val avgFrameTime = frameTimes.average()
            1_000_000_000.0 / avgFrameTime
        } else {
            0.0
        }
        
        // 获取内存使用
        val memoryInfo = ActivityManager.MemoryInfo()
        val activityManager = ctx.getSystemService(Context.ACTIVITY_SERVICE) 
            as ActivityManager
        activityManager.getMemoryInfo(memoryInfo)
        
        val usedMemory = Runtime.getRuntime().totalMemory() - 
                        Runtime.getRuntime().freeMemory()
        val usedMemoryMB = usedMemory / (1024.0 * 1024.0)
        val totalMemoryMB = Runtime.getRuntime().totalMemory() / (1024.0 * 1024.0)
        
        // 计算CPU使用率(简化版)
        val cpuUsage = calculateCpuUsage()
        
        // 计算GPU时间(估算)
        val gpuTimeMs = estimateGpuTime()
        
        // 计算95%帧时间
        val sortedTimes = frameTimeHistory.sorted()
        val index95th = (sortedTimes.size * 0.95).toInt()
        val frameTime95th = if (sortedTimes.isNotEmpty() && index95th < sortedTimes.size) {
            sortedTimes[index95th] / 1_000_000.0f
        } else {
            0f
        }
        
        val info = PerformanceInfo(
            fps = fps.toFloat(),
            usedMemoryMB = usedMemoryMB.toFloat(),
            totalMemoryMB = totalMemoryMB.toFloat(),
            cpuUsage = cpuUsage,
            gpuTimeMs = gpuTimeMs,
            jankCount = jankCount,
            frameTime95th = frameTime95th
        )
        
        // 回调更新
        handler.post {
            onPerformanceUpdate?.invoke(info)
        }
    }
    
    private fun calculateCpuUsage(): Float {
        return try {
            // 读取/proc/stat获取CPU使用率
            val reader = java.io.BufferedReader(
                java.io.InputStreamReader(
                    java.lang.ProcessBuilder("top", "-n", "1").start().inputStream
                )
            )
            
            var cpuUsage = 0f
            var line: String?
            while (reader.readLine().also { line = it } != null) {
                if (line?.contains("CPU") == true) {
                    val parts = line!!.split("\\s+".toRegex())
                    if (parts.size > 8) {
                        val user = parts[2].toFloatOrNull() ?: 0f
                        val system = parts[4].toFloatOrNull() ?: 0f
                        cpuUsage = user + system
                        break
                    }
                }
            }
            reader.close()
            cpuUsage
        } catch (e: Exception) {
            Log.e("PerformanceMonitor", "Error calculating CPU usage", e)
            0f
        }
    }
    
    private fun estimateGpuTime(): Float {
        // 简化估算:基于帧时间和CPU使用率
        if (frameTimeHistory.isEmpty()) return 0f
        
        val avgFrameTime = frameTimeHistory.average()
        val cpuTime = avgFrameTime * 0.4 // 假设40%是CPU时间
        val gpuTime = avgFrameTime - cpuTime
        
        return (gpuTime / 1_000_000).toFloat().coerceAtLeast(0f)
    }
    
    fun getPerformanceInfo(): PerformanceInfo {
        val ctx = activity ?: return PerformanceInfo(0f, 0f, 0f, 0f, 0f, 0, 0f)
        
        // 实时计算当前性能数据
        val currentFps = if (frameTimes.isNotEmpty()) {
            val avgFrameTime = frameTimes.average()
            (1_000_000_000.0 / avgFrameTime).toFloat()
        } else {
            0f
        }
        
        val usedMemory = Runtime.getRuntime().totalMemory() - 
                        Runtime.getRuntime().freeMemory()
        val usedMemoryMB = usedMemory / (1024.0f * 1024.0f)
        
        return PerformanceInfo(
            fps = currentFps,
            usedMemoryMB = usedMemoryMB,
            totalMemoryMB = Runtime.getRuntime().totalMemory() / (1024.0f * 1024.0f),
            cpuUsage = calculateCpuUsage(),
            gpuTimeMs = estimateGpuTime(),
            jankCount = jankCount,
            frameTime95th = 0f // 需要完整历史数据
        )
    }
    
    fun resetJankCount() {
        jankCount = 0
    }
}

4.2 BitmapManager.kt

package com.example.performance.utils

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Build
import android.util.LruCache
import android.util.Size
import kotlin.math.roundToInt

object BitmapManager {
    
    // 内存缓存(使用LRU策略)
    private val memoryCache: LruCache<String, Bitmap>
    
    // 尺寸缓存池
    private val sizeCache = mutableMapOf<Size, MutableList<Bitmap>>()
    
    init {
        // 分配最大内存的1/8作为图片缓存
        val maxMemory = (Runtime.getRuntime().maxMemory() / 1024).toInt()
        val cacheSize = maxMemory / 8
        
        memoryCache = object : LruCache<String, Bitmap>(cacheSize) {
            override fun sizeOf(key: String, bitmap: Bitmap): Int {
                // 返回Bitmap占用的KB数
                return bitmap.allocationByteCount / 1024
            }
            
            override fun entryRemoved(
                evicted: Boolean,
                key: String,
                oldValue: Bitmap,
                newValue: Bitmap?
            ) {
                // 被移除时尝试放入尺寸缓存池
                if (evicted && !oldValue.isRecycled) {
                    cacheBitmapBySize(oldValue)
                }
            }
        }
    }
    
    /**
     * 加载或获取缓存的Bitmap
     */
    fun getOrCreateBitmap(key: String, width: Int, height: Int): Bitmap {
        // 1. 尝试从内存缓存获取
        memoryCache.get(key)?.let { cachedBitmap ->
            if (!cachedBitmap.isRecycled && 
                cachedBitmap.width == width && 
                cachedBitmap.height == height) {
                return cachedBitmap
            }
        }
        
        // 2. 尝试从尺寸缓存池获取
        val size = Size(width, height)
        val pool = sizeCache[size]
        pool?.let {
            synchronized(it) {
                if (it.isNotEmpty()) {
                    val bitmap = it.removeAt(0)
                    if (!bitmap.isRecycled) {
                        // 清空Bitmap内容
                        bitmap.eraseColor(android.graphics.Color.TRANSPARENT)
                        return bitmap
                    }
                }
            }
        }
        
        // 3. 创建新的Bitmap
        return createOptimizedBitmap(width, height).also { bitmap ->
            memoryCache.put(key, bitmap)
        }
    }
    
    /**
     * 创建经过优化的Bitmap
     */
    private fun createOptimizedBitmap(width: Int, height: Int): Bitmap {
        // 根据需求选择合适的配置
        val config = when {
            // 需要透明度
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> 
                Bitmap.Config.ARGB_8888
            // 不需要透明度且节省内存
            else -> Bitmap.Config.RGB_565
        }
        
        return try {
            Bitmap.createBitmap(width, height, config)
        } catch (e: OutOfMemoryError) {
            // 内存不足时尝试清理缓存
            clearCache()
            
            // 尝试使用更小的配置
            val fallbackConfig = Bitmap.Config.RGB_565
            Bitmap.createBitmap(width, height, fallbackConfig)
        }
    }
    
    /**
     * 根据尺寸缓存Bitmap
     */
    private fun cacheBitmapBySize(bitmap: Bitmap) {
        if (bitmap.isRecycled) return
        
        val size = Size(bitmap.width, bitmap.height)
        val pool = sizeCache.getOrPut(size) { mutableListOf() }
        
        synchronized(pool) {
            // 限制池大小,避免占用过多内存
            if (pool.size < 3) {
                pool.add(bitmap)
            } else {
                // 池已满,回收Bitmap
                bitmap.recycle()
            }
        }
    }
    
    /**
     * 解码资源图片并优化
     */
    fun decodeResource(resId: Int, reqWidth: Int, reqHeight: Int): Bitmap {
        val key = "res_${resId}_${reqWidth}x${reqHeight}"
        
        // 检查缓存
        memoryCache.get(key)?.let { return it }
        
        val options = BitmapFactory.Options().apply {
            // 只读取尺寸信息
            inJustDecodeBounds = true
            BitmapFactory.decodeResource(ResourcesProvider.resources, resId, this)
            
            // 计算采样率
            inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight)
            
            // 配置解码参数
            inJustDecodeBounds = false
            inPreferredConfig = Bitmap.Config.RGB_565
            inDither = true
            inScaled = true
            
            // Android 4.4+ 启用位图复用
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                inMutable = true
                
                // 尝试从缓存中获取可复用的Bitmap
                val reusableBitmap = findReusableBitmap(reqWidth, reqHeight)
                reusableBitmap?.let { inBitmap = it }
            }
        }
        
        return try {
            BitmapFactory.decodeResource(ResourcesProvider.resources, resId, options).also {
                memoryCache.put(key, it)
            }
        } catch (e: IllegalArgumentException) {
            // inBitmap复用失败,不使用inBitmap重试
            options.inBitmap = null
            BitmapFactory.decodeResource(ResourcesProvider.resources, resId, options).also {
                memoryCache.put(key, it)
            }
        }
    }
    
    /**
     * 计算合适的采样率
     */
    private fun calculateInSampleSize(
        options: BitmapFactory.Options,
        reqWidth: Int,
        reqHeight: Int
    ): Int {
        val (width, height) = options.run { outWidth to outHeight }
        var inSampleSize = 1
        
        if (height > reqHeight || width > reqWidth) {
            val halfHeight = height / 2
            val halfWidth = width / 2
            
            while (halfHeight / inSampleSize >= reqHeight &&
                   halfWidth / inSampleSize >= reqWidth) {
                inSampleSize *= 2
            }
        }
        
        // 针对高分辨率屏幕进一步优化
        val density = ResourcesProvider.resources.displayMetrics.densityDpi
        if (density > 320 && inSampleSize == 1) {
            inSampleSize = 2
        }
        
        return inSampleSize
    }
    
    /**
     * 查找可复用的Bitmap
     */
    private fun findReusableBitmap(reqWidth: Int, reqHeight: Int): Bitmap? {
        // 1. 从尺寸缓存池查找
        val size = Size(reqWidth, reqHeight)
        val pool = sizeCache[size]
        pool?.let {
            synchronized(it) {
                if (it.isNotEmpty()) {
                    val bitmap = it.removeAt(0)
                    if (!bitmap.isRecycled && 
                        bitmap.width >= reqWidth && 
                        bitmap.height >= reqHeight) {
                        return bitmap
                    }
                }
            }
        }
        
        // 2. 从LRU缓存中查找(需要满足inBitmap的条件)
        memoryCache.snapshot().forEach { (_, bitmap) ->
            if (!bitmap.isRecycled &&
                bitmap.isMutable &&
                bitmap.config != Bitmap.Config.HARDWARE &&
                bitmap.width >= reqWidth &&
                bitmap.height >= reqHeight) {
                return bitmap
            }
        }
        
        return null
    }
    
    /**
     * 清理所有缓存
     */
    fun clearCache() {
        memoryCache.evictAll()
        
        sizeCache.values.forEach { pool ->
            synchronized(pool) {
                pool.forEach { it.recycle() }
                pool.clear()
            }
        }
        sizeCache.clear()
        
        // 建议系统进行垃圾回收
        System.gc()
    }
    
    /**
     * 移除特定缓存
     */
    fun removeCache(key: String) {
        memoryCache.remove(key)
    }
    
    /**
     * 获取缓存统计信息
     */
    fun getCacheStats(): String {
        val hitCount = memoryCache.hitCount()
        val missCount = memoryCache.missCount()
        val hitRate = if (hitCount + missCount > 0) {
            hitCount.toFloat() / (hitCount + missCount) * 100
        } else {
            0f
        }
        
        val totalSize = memoryCache.size()
        val maxSize = memoryCache.maxSize()
        
        val poolSizes = sizeCache.values.sumOf { it.size }
        
        return """
            内存缓存: ${totalSize}KB / ${maxSize}KB
            命中率: ${"%.1f".format(hitRate)}% (${hitCount}/${hitCount + missCount})
            尺寸缓存池: ${poolSizes}个
        """.trimIndent()
    }
    
    /**
     * 资源提供者(避免传递Context)
     */
    object ResourcesProvider {
        lateinit var resources: android.content.res.Resources
        lateinit var context: android.content.Context
        
        fun initialize(context: android.content.Context) {
            this.context = context
            this.resources = context.resources
        }
    }
}

4.3 FrameRateTracker.kt

package com.example.performance.utils

import android.os.Handler
import android.os.Looper
import android.view.Choreographer

class FrameRateTracker {
    
    interface FrameRateListener {
        fun onFrameRateUpdate(fps: Float, droppedFrames: Int)
        fun onJankDetected(frameTimeMs: Long)
    }
    
    private var choreographer: Choreographer? = null
    private var frameCallback: Choreographer.FrameCallback? = null
    private var isTracking = false
    
    private var frameCount = 0
    private var lastFrameTime = 0L
    private var startTime = 0L
    private var droppedFrames = 0
    private val frameTimes = mutableListOf<Long>()
    
    private var listener: FrameRateListener? = null
    private val handler = Handler(Looper.getMainLooper())
    private val reportRunnable = Runnable { reportFrameRate() }
    
    // 配置
    var reportInterval = 1000L // 报告间隔(毫秒)
    var jankThreshold = 16666667L // 卡顿阈值(纳秒),16.67ms
    
    fun startTracking() {
        if (isTracking) return
        
        isTracking = true
        frameCount = 0
        droppedFrames = 0
        lastFrameTime = 0
        startTime = System.nanoTime()
        frameTimes.clear()
        
        choreographer = Choreographer.getInstance()
        frameCallback = object : Choreographer.FrameCallback {
            override fun doFrame(frameTimeNanos: Long) {
                onFrame(frameTimeNanos)
                choreographer?.postFrameCallback(this)
            }
        }
        
        choreographer?.postFrameCallback(frameCallback!!)
        handler.postDelayed(reportRunnable, reportInterval)
        
        android.util.Log.d("FrameRateTracker", "Started tracking")
    }
    
    fun stopTracking() {
        if (!isTracking) return
        
        isTracking = false
        frameCallback?.let { choreographer?.removeFrameCallback(it) }
        handler.removeCallbacks(reportRunnable)
        frameCallback = null
        choreographer = null
        
        reportFrameRate() // 最终报告
        
        android.util.Log.d("FrameRateTracker", "Stopped tracking")
    }
    
    private fun onFrame(frameTimeNanos: Long) {
        if (lastFrameTime > 0) {
            val frameTime = frameTimeNanos - lastFrameTime
            frameTimes.add(frameTime)
            
            // 检测掉帧
            if (frameTime > jankThreshold * 1.5) {
                val dropped = ((frameTime - jankThreshold) / jankThreshold).toInt()
                droppedFrames += dropped.coerceAtLeast(1)
                
                // 报告卡顿
                if (frameTime > jankThreshold * 2) {
                    listener?.onJankDetected(frameTime / 1_000_000)
                }
            }
        }
        
        lastFrameTime = frameTimeNanos
        frameCount++
    }
    
    private fun reportFrameRate() {
        if (!isTracking) return
        
        val elapsed = (System.nanoTime() - startTime) / 1_000_000_000.0
        val fps = if (elapsed > 0) frameCount / elapsed else 0.0
        
        // 计算帧时间统计数据
        val stats = calculateFrameTimeStats()
        
        listener?.onFrameRateUpdate(fps.toFloat(), droppedFrames)
        
        // 重置计数器
        frameCount = 0
        droppedFrames = 0
        startTime = System.nanoTime()
        frameTimes.clear()
        
        // 安排下一次报告
        handler.postDelayed(reportRunnable, reportInterval)
    }
    
    private fun calculateFrameTimeStats(): FrameTimeStats {
        if (frameTimes.isEmpty()) return FrameTimeStats()
        
        val sorted = frameTimes.sorted()
        val average = frameTimes.average()
        val p50 = sorted[sorted.size / 2]
        val p90 = sorted[(sorted.size * 0.9).toInt()]
        val p95 = sorted[(sorted.size * 0.95).toInt()]
        val p99 = sorted[(sorted.size * 0.99).toInt()]
        
        return FrameTimeStats(
            average = average,
            p50 = p50,
            p90 = p90,
            p95 = p95,
            p99 = p99
        )
    }
    
    fun setFrameRateListener(listener: FrameRateListener) {
        this.listener = listener
    }
    
    data class FrameTimeStats(
        val average: Double = 0.0,
        val p50: Long = 0,
        val p90: Long = 0,
        val p95: Long = 0,
        val p99: Long = 0
    ) {
        override fun toString(): String {
            return """
                Average: ${(average / 1_000_000).format(2)}ms
                P50: ${(p50 / 1_000_000).format(2)}ms
                P90: ${(p90 / 1_000_000).format(2)}ms
                P95: ${(p95 / 1_000_000).format(2)}ms
                P99: ${(p99 / 1_000_000).format(2)}ms
            """.trimIndent()
        }
        
        private fun Double.format(digits: Int) = "%.${digits}f".format(this)
        private fun Long.format(digits: Int) = "%.${digits}f".format(this / 1_000_000.0)
    }
}

5. 性能测试页面

5.1 BenchmarkActivity.kt

package com.example.performance.performance

import android.annotation.SuppressLint
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.example.performance.R
import com.example.performance.utils.FrameRateTracker
import com.example.performance.utils.PerformanceMonitor
import kotlin.math.roundToInt

class BenchmarkActivity : AppCompatActivity(), FrameRateTracker.FrameRateListener {
    
    private lateinit var tvResults: TextView
    private lateinit var btnStartTest: Button
    private lateinit var btnStopTest: Button
    
    private val frameRateTracker = FrameRateTracker()
    private val handler = Handler(Looper.getMainLooper())
    private var isTesting = false
    private var testStartTime = 0L
    
    // 测试结果
    private val fpsHistory = mutableListOf<Float>()
    private val memoryHistory = mutableListOf<Float>()
    private var totalJanks = 0
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_benchmark)
        
        initViews()
        setupFrameRateTracker()
    }
    
    private fun initViews() {
        tvResults = findViewById(R.id.tvResults)
        btnStartTest = findViewById(R.id.btnStartTest)
        btnStopTest = findViewById(R.id.btnStopTest)
        
        btnStartTest.setOnClickListener { startBenchmark() }
        btnStopTest.setOnClickListener { stopBenchmark() }
        
        // 初始化PerformanceMonitor
        PerformanceMonitor.ResourcesProvider.initialize(this)
        PerformanceMonitor.startMonitoring(this)
    }
    
    private fun setupFrameRateTracker() {
        frameRateTracker.reportInterval = 500L
        frameRateTracker.jankThreshold = 16666667L // 60fps阈值
        frameRateTracker.setFrameRateListener(this)
    }
    
    @SuppressLint("SetTextI18n")
    private fun startBenchmark() {
        if (isTesting) return
        
        isTesting = true
        testStartTime = System.currentTimeMillis()
        fpsHistory.clear()
        memoryHistory.clear()
        totalJanks = 0
        
        frameRateTracker.startTracking()
        
        // 开始收集性能数据
        handler.post(object : Runnable {
            override fun run() {
                if (isTesting) {
                    val info = PerformanceMonitor.getPerformanceInfo()
                    memoryHistory.add(info.usedMemoryMB)
                    
                    // 更新UI
                    updateResults()
                    
                    handler.postDelayed(this, 1000)
                }
            }
        })
        
        btnStartTest.isEnabled = false
        btnStopTest.isEnabled = true
        
        tvResults.text = "性能测试开始...\n"
    }
    
    private fun stopBenchmark() {
        if (!isTesting) return
        
        isTesting = false
        frameRateTracker.stopTracking()
        
        btnStartTest.isEnabled = true
        btnStopTest.isEnabled = false
        
        // 生成最终报告
        generateFinalReport()
    }
    
    @SuppressLint("SetTextI18n")
    private fun updateResults() {
        val duration = (System.currentTimeMillis() - testStartTime) / 1000
        val currentFps = fpsHistory.lastOrNull() ?: 0f
        val currentMemory = memoryHistory.lastOrNull() ?: 0f
        
        val results = """
            测试时间: ${duration}秒
            当前FPS: ${"%.1f".format(currentFps)}
            当前内存: ${"%.1f".format(currentMemory)}MB
            卡顿次数: ${totalJanks}
            平均FPS: ${calculateAverageFps()}
            最大内存: ${"%.1f".format(memoryHistory.maxOrNull() ?: 0f)}MB
        """.trimIndent()
        
        tvResults.text = results
    }
    
    private fun calculateAverageFps(): String {
        return if (fpsHistory.isNotEmpty()) {
            "%.1f".format(fpsHistory.average())
        } else {
            "0.0"
        }
    }
    
    @SuppressLint("SetTextI18n")
    private fun generateFinalReport() {
        if (fpsHistory.isEmpty() || memoryHistory.isEmpty()) return
        
        val avgFps = fpsHistory.average()
        val minFps = fpsHistory.minOrNull() ?: 0f
        val maxFps = fpsHistory.maxOrNull() ?: 0f
        
        val avgMemory = memoryHistory.average()
        val minMemory = memoryHistory.minOrNull() ?: 0f
        val maxMemory = memoryHistory.maxOrNull() ?: 0f
        
        val duration = (System.currentTimeMillis() - testStartTime) / 1000
        
        val report = """
            ====== 性能测试报告 ======
            测试时长: ${duration}秒
            
            🎯 帧率表现:
            平均FPS: ${"%.1f".format(avgFps)}
            最低FPS: ${"%.1f".format(minFps)}
            最高FPS: ${"%.1f".format(maxFps)}
            卡顿次数: ${totalJanks}
            
            💾 内存表现:
            平均内存: ${"%.1f".format(avgMemory)}MB
            最低内存: ${"%.1f".format(minMemory)}MB
            最高内存: ${"%.1f".format(maxMemory)}MB
            
            📊 性能评级:
            ${getPerformanceRating(avgFps, totalJanks)}
            
            💡 优化建议:
            ${getOptimizationSuggestions(avgFps, totalJanks, maxMemory)}
        """.trimIndent()
        
        tvResults.text = report
    }
    
    private fun getPerformanceRating(avgFps: Double, janks: Int): String {
        return when {
            avgFps >= 55 && janks < 5 -> "✅ 优秀 (流畅)"
            avgFps >= 45 && janks < 10 -> "⚠️ 良好 (基本流畅)"
            avgFps >= 30 && janks < 20 -> "⚠️ 一般 (偶有卡顿)"
            else -> "❌ 较差 (需要优化)"
        }
    }
    
    private fun getOptimizationSuggestions(
        avgFps: Double, 
        janks: Int, 
        maxMemory: Float
    ): String {
        val suggestions = mutableListOf<String>()
        
        if (avgFps < 45) {
            suggestions.add("- 检查过度绘制,减少不必要的View层级")
            suggestions.add("- 启用硬件加速,优化绘制操作")
            suggestions.add("- 使用异步绘制或RenderThread")
        }
        
        if (janks > 10) {
            suggestions.add("- 避免在主线程进行耗时操作")
            suggestions.add("- 优化动画,使用ValueAnimator替代Thread")
            suggestions.add("- 减少每帧的绘制内容")
        }
        
        if (maxMemory > 100) {
            suggestions.add("- 优化Bitmap内存使用")
            suggestions.add("- 及时回收不再使用的资源")
            suggestions.add("- 使用内存缓存和对象池")
        }
        
        if (suggestions.isEmpty()) {
            suggestions.add("✅ 当前性能表现良好,继续保持!")
        }
        
        return suggestions.joinToString("\n")
    }
    
    // FrameRateListener实现
    override fun onFrameRateUpdate(fps: Float, droppedFrames: Int) {
        fpsHistory.add(fps)
        totalJanks += droppedFrames
    }
    
    override fun onJankDetected(frameTimeMs: Long) {
        // 记录详细卡顿信息
        android.util.Log.w("Benchmark", "Jank detected: ${frameTimeMs}ms")
    }
    
    override fun onDestroy() {
        super.onDestroy()
        stopBenchmark()
        PerformanceMonitor.stopMonitoring()
    }
}

5.2 PerformancePanel.kt (自定义性能面板View)

package com.example.performance.performance

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import com.example.performance.utils.PerformanceMonitor
import kotlin.math.max
import kotlin.math.min

class PerformancePanel @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    
    // 绘制配置
    private val fpsPaint = Paint().apply {
        color = Color.WHITE
        textSize = 32f
        typeface = Typeface.MONOSPACE
        isAntiAlias = true
    }
    
    private val memoryPaint = Paint().apply {
        color = Color.parseColor("#4CAF50")
        style = Paint.Style.FILL
        isAntiAlias = true
    }
    
    private val cpuPaint = Paint().apply {
        color = Color.parseColor("#2196F3")
        style = Paint.Style.FILL
        isAntiAlias = true
    }
    
    private val gpuPaint = Paint().apply {
        color = Color.parseColor("#FF9800")
        style = Paint.Style.FILL
        isAntiAlias = true
    }
    
    private val gridPaint = Paint().apply {
        color = Color.parseColor("#444444")
        style = Paint.Style.STROKE
        strokeWidth = 1f
        isAntiAlias = true
    }
    
    private val bgPaint = Paint().apply {
        color = Color.parseColor("#22000000")
        style = Paint.Style.FILL
        isAntiAlias = true
    }
    
    // 数据存储
    private val fpsHistory = FloatArray(100)
    private val memoryHistory = FloatArray(100)
    private val cpuHistory = FloatArray(100)
    private val gpuHistory = FloatArray(100)
    private var historyIndex = 0
    private var historySize = 0
    
    // 性能阈值
    private val fpsThresholds = arrayOf(30f, 45f, 55f)
    private val memoryThresholds = arrayOf(50f, 100f, 200f)
    private val cpuThresholds = arrayOf(30f, 60f, 80f)
    private val gpuThresholds = arrayOf(8.3f, 16.6f, 33.3f) // ms
    
    init {
        // 注册性能监听
        PerformanceMonitor.onPerformanceUpdate = { info ->
            synchronized(this) {
                fpsHistory[historyIndex] = info.fps
                memoryHistory[historyIndex] = info.usedMemoryMB
                cpuHistory[historyIndex] = info.cpuUsage
                gpuHistory[historyIndex] = info.gpuTimeMs
                
                historyIndex = (historyIndex + 1) % fpsHistory.size
                historySize = min(historySize + 1, fpsHistory.size)
                
                postInvalidate()
            }
        }
    }
    
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        
        // 绘制背景
        canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), bgPaint)
        
        // 绘制网格
        drawGrid(canvas)
        
        // 绘制性能图表
        drawPerformanceCharts(canvas)
        
        // 绘制实时数据
        drawRealTimeData(canvas)
        
        // 绘制性能评级
        drawPerformanceRating(canvas)
    }
    
    private fun drawGrid(canvas: Canvas) {
        val gridSize = 50f
        
        // 垂直线
        var x = 0f
        while (x < width) {
            canvas.drawLine(x, 0f, x, height.toFloat(), gridPaint)
            x += gridSize
        }
        
        // 水平线
        var y = 0f
        while (y < height) {
            canvas.drawLine(0f, y, width.toFloat(), y, gridPaint)
            y += gridSize
        }
    }
    
    private fun drawPerformanceCharts(canvas: Canvas) {
        if (historySize < 2) return
        
        val chartHeight = height * 0.6f
        val chartTop = height * 0.1f
        val chartBottom = chartTop + chartHeight
        val chartWidth = width.toFloat()
        val pointSpacing = chartWidth / (historySize - 1)
        
        // 绘制FPS曲线
        drawCurve(canvas, fpsHistory, historySize, pointSpacing, chartTop, 
                 chartBottom, 0f, 120f, fpsPaint)
        
        // 绘制内存曲线
        drawCurve(canvas, memoryHistory, historySize, pointSpacing, chartTop,
                 chartBottom, 0f, 500f, memoryPaint)
        
        // 绘制CPU曲线
        drawCurve(canvas, cpuHistory, historySize, pointSpacing, chartTop,
                 chartBottom, 0f, 100f, cpuPaint)
        
        // 绘制GPU曲线
        drawCurve(canvas, gpuHistory, historySize, pointSpacing, chartTop,
                 chartBottom, 0f, 50f, gpuPaint)
    }
    
    private fun drawCurve(
        canvas: Canvas,
        data: FloatArray,
        size: Int,
        pointSpacing: Float,
        top: Float,
        bottom: Float,
        minValue: Float,
        maxValue: Float,
        paint: Paint
    ) {
        val path = Path()
        val range = maxValue - minValue
        val chartHeight = bottom - top
        
        // 计算第一个点
        var lastIndex = (historyIndex - size + data.size) % data.size
        var lastValue = data[lastIndex]
        var lastY = bottom - ((lastValue - minValue) / range) * chartHeight
        
        path.moveTo(0f, lastY.coerceIn(top, bottom))
        
        // 绘制曲线
        for (i in 1 until size) {
            val index = (lastIndex + 1) % data.size
            val value = data[index]
            val x = i * pointSpacing
            val y = bottom - ((value - minValue) / range) * chartHeight
            
            // 使用贝塞尔曲线平滑连接
            val controlX = x - pointSpacing / 2
            path.cubicTo(
                controlX, lastY,
                controlX, y,
                x, y.coerceIn(top, bottom)
            )
            
            lastIndex = index
            lastValue = value
            lastY = y
        }
        
        canvas.drawPath(path, paint)
    }
    
    private fun drawRealTimeData(canvas: Canvas) {
        val currentIndex = (historyIndex - 1 + fpsHistory.size) % fpsHistory.size
        val fps = fpsHistory[currentIndex]
        val memory = memoryHistory[currentIndex]
        val cpu = cpuHistory[currentIndex]
        val gpu = gpuHistory[currentIndex]
        
        val textX = 20f
        var textY = 50f
        val lineHeight = 35f
        
        // FPS
        fpsPaint.color = getColorForValue(fps, fpsThresholds, 
            arrayOf(Color.GREEN, Color.YELLOW, Color.RED))
        canvas.drawText("FPS: ${"%.1f".format(fps)}", textX, textY, fpsPaint)
        
        // 内存
        textY += lineHeight
        fpsPaint.color = getColorForValue(memory, memoryThresholds,
            arrayOf(Color.GREEN, Color.YELLOW, Color.RED))
        canvas.drawText("内存: ${"%.1f".format(memory)}MB", textX, textY, fpsPaint)
        
        // CPU
        textY += lineHeight
        fpsPaint.color = getColorForValue(cpu, cpuThresholds,
            arrayOf(Color.GREEN, Color.YELLOW, Color.RED))
        canvas.drawText("CPU: ${"%.1f".format(cpu)}%", textX, textY, fpsPaint)
        
        // GPU
        textY += lineHeight
        fpsPaint.color = getColorForValue(gpu, gpuThresholds,
            arrayOf(Color.GREEN, Color.YELLOW, Color.RED))
        canvas.drawText("GPU: ${"%.1f".format(gpu)}ms", textX, textY, fpsPaint)
    }
    
    private fun drawPerformanceRating(canvas: Canvas) {
        val currentIndex = (historyIndex - 1 + fpsHistory.size) % fpsHistory.size
        val fps = fpsHistory[currentIndex]
        val memory = memoryHistory[currentIndex]
        val cpu = cpuHistory[currentIndex]
        
        val rating = calculatePerformanceRating(fps, memory, cpu)
        
        val ratingPaint = Paint().apply {
            color = rating.color
            textSize = 24f
            typeface = Typeface.DEFAULT_BOLD
            isAntiAlias = true
        }
        
        val text = "性能评级: ${rating.text}"
        val textWidth = ratingPaint.measureText(text)
        val x = width - textWidth - 20
        val y = 50f
        
        canvas.drawText(text, x, y, ratingPaint)
    }
    
    private fun getColorForValue(
        value: Float,
        thresholds: Array<Float>,
        colors: Array<Int>
    ): Int {
        return when {
            value < thresholds[0] -> colors[0]
            value < thresholds[1] -> colors[1]
            value < thresholds[2] -> colors[1]
            else -> colors[2]
        }
    }
    
    private fun calculatePerformanceRating(
        fps: Float,
        memory: Float,
        cpu: Float
    ): PerformanceRating {
        var score = 0
        
        // FPS评分
        score += when {
            fps >= 55 -> 3
            fps >= 45 -> 2
            fps >= 30 -> 1
            else -> 0
        }
        
        // 内存评分
        score += when {
            memory < 50 -> 3
            memory < 100 -> 2
            memory < 200 -> 1
            else -> 0
        }
        
        // CPU评分
        score += when {
            cpu < 30 -> 3
            cpu < 60 -> 2
            cpu < 80 -> 1
            else -> 0
        }
        
        return when (score) {
            in 8..9 -> PerformanceRating("优秀", Color.GREEN)
            in 5..7 -> PerformanceRating("良好", Color.YELLOW)
            in 3..4 -> PerformanceRating("一般", Color.parseColor("#FF9800"))
            else -> PerformanceRating("较差", Color.RED)
        }
    }
    
    data class PerformanceRating(val text: String, val color: Int)
    
    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        PerformanceMonitor.onPerformanceUpdate = null
    }
}

6. 项目配置文件

6.1 build.gradle.kts (模块级)

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
}

android {
    namespace = "com.example.performance"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.example.performance"
        minSdk = 21
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        
        // 启用多Dex(如果方法数超过限制)
        multiDexEnabled = true
    }

    buildTypes {
        release {
            isMinifyEnabled = true
            isShrinkResources = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
            
            // 启用R8完整模式
            isDebuggable = false
            isJniDebuggable = false
            isRenderscriptDebuggable = false
        }
        
        debug {
            // 启用调试功能
            isDebuggable = true
            isJniDebuggable = true
            isRenderscriptDebuggable = true
            
            // 调试版本不进行代码优化,便于性能分析
            isMinifyEnabled = false
            isShrinkResources = false
            
            // 添加调试配置
            applicationIdSuffix = ".debug"
            versionNameSuffix = "-DEBUG"
        }
    }
    
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    
    kotlinOptions {
        jvmTarget = "1.8"
    }
    
    buildFeatures {
        viewBinding = true
        buildConfig = true
    }
    
    // 启用数据绑定
    dataBinding {
        enable = true
    }
    
    // 开启lint检查但不在构建时失败
    lint {
        abortOnError = false
        warningsAsErrors = true
    }
}

dependencies {
    // AndroidX Core
    implementation("androidx.core:core-ktx:1.12.0")
    implementation("androidx.appcompat:appcompat:1.6.1")
    
    // Material Design
    implementation("com.google.android.material:material:1.11.0")
    
    // Constraint Layout
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
    
    // CardView
    implementation("androidx.cardview:cardview:1.0.0")
    
    // RecyclerView
    implementation("androidx.recyclerview:recyclerview:1.3.2")
    
    // Lifecycle
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
    
    // 多Dex支持
    implementation("androidx.multidex:multidex:2.0.1")
    
    // 测试依赖
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
    
    // 性能监控工具
    debugImplementation("androidx.profileinstaller:profileinstaller:1.3.1")
}

6.2 AndroidManifest.xml

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

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    
    <!-- 调试权限 -->
    <uses-permission android:name="android.permission.DUMP" tools:ignore="ProtectedPermissions" />
    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" 
        tools:ignore="ProtectedPermissions" />

    <application
        android:name=".PerformanceApplication"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.PerformanceDemo"
        android:hardwareAccelerated="true"
        android:largeHeap="true"
        android:usesCleartextTraffic="true"
        tools:targetApi="31">
        
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:configChanges="orientation|screenSize|keyboardHidden"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <activity
            android:name=".performance.BenchmarkActivity"
            android:exported="false"
            android:theme="@style/Theme.PerformanceDemo.NoActionBar" />
        
        <meta-data
            android:name="android.max_aspect"
            android:value="2.1" />
            
        <meta-data
            android:name="android.notch_support"
            android:value="true" />
            
        <!-- 启用Profileable(Android 10+) -->
        <profileable
            android:shell="true"
            tools:targetApi="q" />
    </application>

</manifest>

6.3 PerformanceApplication.kt

package com.example.performance

import android.app.Application
import android.os.StrictMode
import com.example.performance.utils.BitmapManager
import com.example.performance.utils.PerformanceMonitor

class PerformanceApplication : Application() {
    
    override fun onCreate() {
        super.onCreate()
        
        // 初始化BitmapManager
        BitmapManager.ResourcesProvider.initialize(this)
        
        // 开发模式下启用严格模式检测
        if (BuildConfig.DEBUG) {
            enableStrictMode()
        }
        
        // 初始化性能监控
        initializePerformanceMonitoring()
    }
    
    private fun enableStrictMode() {
        StrictMode.setThreadPolicy(
            StrictMode.ThreadPolicy.Builder()
                .detectAll() // 检测所有违规
                .penaltyLog() // 记录日志
                .penaltyDeathOnNetwork() // 禁止网络在主线程
                .penaltyFlashScreen() // 屏幕闪烁提示
                .build()
        )
        
        StrictMode.setVmPolicy(
            StrictMode.VmPolicy.Builder()
                .detectAll()
                .penaltyLog()
                .detectLeakedClosableObjects() // 检测未关闭的对象
                .detectLeakedRegistrationObjects() // 检测未取消的注册
                .detectLeakedSqlLiteObjects() // 检测SQLite泄漏
                .build()
        )
    }
    
    private fun initializePerformanceMonitoring() {
        // 可以在Application级别启动全局性能监控
        if (BuildConfig.DEBUG) {
            // 开发模式下启动基础监控
            Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
                // 记录未捕获的异常
                android.util.Log.e("PerformanceApp", 
                    "Uncaught exception in thread: ${thread.name}", 
                    throwable)
                
                // 调用默认处理器
                Thread.getDefaultUncaughtExceptionHandler()?.uncaughtException(thread, throwable)
            }
        }
    }
    
    override fun onLowMemory() {
        super.onLowMemory()
        
        // 内存不足时清理缓存
        BitmapManager.clearCache()
        
        // 通知所有Activity
        android.util.Log.w("PerformanceApp", "Low memory warning, clearing caches")
    }
    
    override fun onTrimMemory(level: Int) {
        super.onTrimMemory(level)
        
        // 根据Trim级别清理资源
        when (level) {
            ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE,
            ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW -> {
                // 清理部分缓存
                BitmapManager.clearCache()
            }
            ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL,
            ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN -> {
                // 清理所有可能的内存
                BitmapManager.clearCache()
                System.gc()
            }
        }
        
        android.util.Log.i("PerformanceApp", "Trim memory level: $level")
    }
}

性能优化要点

1. 绘制优化

  • ✅ 启用硬件加速 (setLayerType(LAYER_TYPE_HARDWARE, null))

  • ✅ 避免在onDraw中创建对象

  • ✅ 使用局部刷新 (invalidate(left, top, right, bottom))

  • ✅ 预计算路径和矩形

  • ✅ 复用Paint和Shader对象

2. 内存优化

  • ✅ 使用LRU缓存管理Bitmap

  • ✅ 实现Bitmap复用池

  • ✅ 及时回收不再使用的资源

  • ✅ 使用对象池避免频繁GC

3. 动画优化

  • ✅ 使用ValueAnimator替代Thread

  • ✅ 高刷新率设备适配

  • ✅ 使用Choreographer同步Vsync

  • ✅ 动画插值器优化

4. 异步优化

  • ✅ 使用RenderThread异步绘制

  • ✅ 离屏渲染缓存

  • ✅ 后台线程计算,主线程更新

常见问题排查

问题1: 硬件加速导致崩溃

// 解决方案:检查不支持硬件加速的操作
override fun onDraw(canvas: Canvas) {
    if (canvas.isHardwareAccelerated) {
        // 使用硬件加速绘制路径
        drawHardware(canvas)
    } else {
        // 软件回退
        drawSoftware(canvas)
    }
}

问题2: 内存泄漏

// 在View销毁时清理资源
override fun onDetachedFromWindow() {
    super.onDetachedFromWindow()
    animator?.cancel()
    bitmap?.recycle()
    handler.removeCallbacksAndMessages(null)
}

问题3: 高刷新率设备掉帧

// 适配不同刷新率
val display = context.display
val refreshRate = display?.refreshRate ?: 60f
val frameTime = 1000f / refreshRate

// 根据刷新率调整动画时长
animator.duration = (frameTime * 60).toLong()

这个完整的Demo项目展示了自定义View性能优化的完整解决方案,从问题定位到优化实现,再到性能监控和测试,提供了全方位的性能优化参考。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐