首页 > 解决方案 > Android Canvas.drawText()双十进制数无法正确呈现

问题描述

尝试将某些文本与数字一起呈现时,我会出现奇怪的行为。问题很可能与线程有关。我的问题是,当我使用 Canvas.drawText() 绘制时,数字始终显示为 0.0,但如果我使用 Log.d(),数字不是 0.0,而是大约 60。

这是我的代码:

游戏视图:

class GameView(
    context: Context?,
    attrs: AttributeSet
) : SurfaceView(context, attrs), SurfaceHolder.Callback {
    private var gameLoop: GameLoop = GameLoop(this, holder)
    private val paint: Paint = Paint()

    init {
        holder.addCallback(this)
        isFocusable = true
    }

    fun update() {
        // TODO: update game state
    }

    override fun surfaceCreated(surfaceHolder: SurfaceHolder) {
        gameLoop.startLoop()
    }

    override fun surfaceChanged(surfaceHolder: SurfaceHolder, p1: Int, p2: Int, p3: Int) {
        // do nothing
    }

    override fun surfaceDestroyed(surfaceHolder: SurfaceHolder) {
        gameLoop.stopLoop()
    }

    override fun draw(drawCanvas: Canvas) {
        super.draw(drawCanvas)
        drawInfo(drawCanvas)
    }

    private fun drawInfo(canvas: Canvas) {
        val averageUps = gameLoop.getAverageUps()
        val averageFps = gameLoop.getAverageFps()

        val color = ContextCompat.getColor(context, DEBUG_TEXT_COLOR)
        paint.color = color
        paint.textSize = DEBUG_TEXT_SIZE

        canvas.drawText("UPS: $averageUps", 40f, DEBUG_TEXT_SIZE, paint)
        canvas.drawText("FPS: $averageFps", 40f, DEBUG_TEXT_SIZE*2 + 10f, paint)
    }

    companion object {
        const val DEBUG_TEXT_SIZE = 40f
        const val DEBUG_TEXT_COLOR = R.color.light_blue_A200
    }
}

游戏循环:

class GameLoop(
    private val gameView: GameView,
    private val surfaceHolder: SurfaceHolder
) : Thread() {
    private var isRunning: Boolean = false
    private var averageUps: Double = 0.0
    private var averageFps: Double = 0.0

    fun getAverageUps(): Double {
        return averageUps
    }

    fun getAverageFps(): Double {
        return averageFps
    }

    fun startLoop() {
        isRunning = true
        start()
    }

    override fun run() {
        super.run()

        var updateCount = 0
        var frameCount = 0

        var startTime = 0L
        var elapsedTime = 0L
        var sleepTime = 0L

        var canvas: Canvas? = null
        startTime = System.currentTimeMillis()
        while (isRunning) {
            try {
                canvas = surfaceHolder.lockCanvas()
                synchronized(canvas) {
                    gameView.update()
                    updateCount++
                    gameView.draw(canvas)
                }
            } catch (iae: IllegalArgumentException) {
                iae.printStackTrace()
            } finally {
                if (canvas != null) {
                    surfaceHolder.unlockCanvasAndPost(canvas)
                    frameCount++
                }
            }

            elapsedTime = System.currentTimeMillis() - startTime
            sleepTime = (updateCount*UPS_PERIOD - elapsedTime)
            if (sleepTime > 0) {
                try {
                    sleep(sleepTime)
                } catch (ie: InterruptedException) {
                    ie.printStackTrace()
                }
            }

            while (sleepTime < 0 && updateCount < MAX_UPS-1) {
                gameView.update()
                updateCount++
                elapsedTime = System.currentTimeMillis() - startTime
                sleepTime = (updateCount*UPS_PERIOD - elapsedTime)
            }

            elapsedTime = System.currentTimeMillis() - startTime
            if (elapsedTime >= 1000.0) {
                averageUps = updateCount.toDouble() / (elapsedTime/1000.0)
                averageFps = frameCount.toDouble() / (elapsedTime/1000.0)
                updateCount = 0
                frameCount = 0
                startTime = System.currentTimeMillis()
            }
        }
    }

    fun stopLoop() {
        // TODO: finish me...
    }

    companion object {
        private const val MAX_UPS: Long = 60
        const val UPS_PERIOD: Long = 1000/MAX_UPS
    }
}

问题出在 GameView.drawInfo(canvas: Canvas) 中。输出始终是“UPS:0.0 FPS:0.0”,但是当我注销 averageUps 和 averageFps 时,它们都在 ~60 左右。

我希望你能帮我解决这个问题:-)

标签: androidmultithreadingkotlincanvasdraw

解决方案


回答我自己的问题:问题出在包含 GameView 的活动中。我在 xml 中有 GameView。当我手动实例化 GameView 并将其与 setContentView(gameView) 一起使用时,所有渲染都开始工作。


推荐阅读