Surface has already been released: при рисовании с помощью Canvas

Рейтинг: 1Ответов: 0Опубликовано: 09.01.2023

Моя программа рисует овал когда мы нажимаем на экран и + меняет координаты овала в зависимости от координат удерживаемого пальца. Когда палец отпускаем, овал должен исчезнуть.

Сейчас когда я нажимаю на экран то получаю свой овал и + когда перемещаю палец то овал всегда рядом с ним, но когда я отпускаю палец то получаю ошибку:

E/Surface: freeAllBuffers: 1 buffers were freed while being dequeued!
E/AndroidRuntime: FATAL EXCEPTION: Thread-2
Process: com.example.lab10, PID: 24198
java.lang.IllegalStateException: Surface has already been released.
at android.view.Surface.checkNotReleasedLocked(Surface.java:774)
at android.view.Surface.unlockCanvasAndPost(Surface.java:473)
> at android.view.SurfaceView$1.unlockCanvasAndPost(SurfaceView.java:1629)
> at com.example.lab10.TaskSix$OvalsView.surfaceCreated$lambda$0(TaskSix.kt:136)
> at com.example.lab10.TaskSix$OvalsView.$r8$lambda$fxYnyciEdLkjDqbt7r8jlbaJ-60(Unknown Source:0)
>at com.example.lab10.TaskSix$OvalsView$$ExternalSyntheticLambda0.run(Unknown Source:2)
>at java.lang.Thread.run(Thread.java:1012)


    package com.example.lab10
    
    import android.annotation.SuppressLint
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    
    
    import android.content.Context
    import android.graphics.Canvas
    import android.graphics.Color
    import android.graphics.Paint
    import android.util.DisplayMetrics
    import android.util.Log
    import android.view.MotionEvent
    import android.view.SurfaceHolder
    import android.view.SurfaceView
    import android.view.View
    import android.view.WindowManager
    import androidx.constraintlayout.widget.ConstraintLayout
    
    class TaskSix : AppCompatActivity() {
        @SuppressLint("ClickableViewAccessibility")
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_task_six)
    
            title = "Task#6"
    
            val layout = findViewById<ConstraintLayout>(R.id.layout)
            val ovalsView =  OvalsView(this)
    
            layout.setOnTouchListener(View.OnTouchListener { view, motionEvent ->
                when (motionEvent.getActionMasked()) {
                    MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
                        Log.d("qqq", "down")
                        val ID: Int = motionEvent.getPointerId(motionEvent.getActionIndex())
                        Log.d("qqq", "element with id: $ID")
    
    
                        layout.addView(ovalsView)
    
                    }
                    MotionEvent.ACTION_MOVE -> {
                        Log.d("qqq", "move")
                        var idx = 0
                        while (idx < motionEvent.pointerCount) {
                            val ID: Int = motionEvent.getPointerId(idx) // pobranie unikalnego id dla każdego dotyku
                            idx++
    
                            ovalsView._top = motionEvent.y
                            ovalsView._left = motionEvent.x
                        }
                    }
                    MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
                        Log.d("qqq", "up")
    
                        layout.removeView(ovalsView)
    
                    }
                    else -> Log.d("qqq", "unhandled")
                }
                return@OnTouchListener true
            })
    
        }
    
        private class OvalsView(context: Context) : SurfaceView(context), SurfaceHolder.Callback {
            private val mSurfaceHolder: SurfaceHolder
            private val mPainter = Paint()
            private var mDrawingThread: Thread? = null
            private val mDisplay = DisplayMetrics()
            private var mDisplayWidth: Int
            private var mDisplayHeight: Int
            private var mRotation = 0f
    
            var _top: Float = 0f
            var _left: Float = 0f
    
            init {
                val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
                wm.defaultDisplay.getMetrics(mDisplay)
                mDisplayWidth = mDisplay.widthPixels
                mDisplayHeight = mDisplay.heightPixels
                mPainter.isAntiAlias = true
                mPainter.color = Color.RED
                mSurfaceHolder = holder
                mSurfaceHolder.addCallback(this)
            }
    
            private fun animateOvals(): Boolean {
                mRotation += 1
                return true
            }
            private fun drawWheel(canvas: Canvas) {
                canvas.drawColor(Color.WHITE)
    //            canvas.rotate(mRotation, mDisplayWidth / 2f, mDisplayHeight / 2f)
    
                //drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)
    
    //            canvas.drawOval(mDisplayWidth/2f - 100f/2f - 100f, mDisplayHeight/2 + 100f/2f,
    //                mDisplayWidth/2f + 100f/2f + 100f, mDisplayHeight/2f - 100/2f, mPainter)
    
                if (_top > 0f && _left > 0f)
                    canvas.drawOval(_left, _top, _left + 200f, _top + 350f, mPainter)
            }
    
            override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
                mDisplayWidth = w
                mDisplayHeight = h
                super.onSizeChanged(w, h, oldw, oldh)
            }
    
            override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
            }
    
            override fun surfaceDestroyed(holder: SurfaceHolder) {
                if (mDrawingThread != null) {
                    mDrawingThread!!.interrupt()
                }
    
            }
    
            override fun surfaceCreated(holder: SurfaceHolder) {
    
                mDrawingThread = Thread(Runnable {
                    var MAX_FRAME_TIME = 1000/60
    
                    var frameStartTime = System.nanoTime();
                    var frameTime: Long = 0
                    var canvas: Canvas? = null
                    while (!Thread.currentThread().isInterrupted && animateOvals()) {
    
                        canvas = mSurfaceHolder.lockCanvas()
                        if (canvas != null) {
                            drawWheel(canvas)
                            mSurfaceHolder.unlockCanvasAndPost(canvas)
                        }
    
    
                        frameTime = (System.nanoTime() - frameStartTime) / 1000000
                        if (frameTime < MAX_FRAME_TIME) // faster than the max fps - limit the FPS
                        {
                            try {
                                Thread.sleep(MAX_FRAME_TIME - frameTime)
                            } catch (e: InterruptedException) {
                                // ignore
                            }
                        }
                    }
                })
                mDrawingThread!!.start()
            }
        }
    }

Ответы

Ответов пока нет.