当前位置: 首页 > 面试题库 >

Android Canvas锁定引发IllegalArgumentException

鲁龙野
2023-03-14
问题内容

我正在尝试实现自己的自定义SurfaceView,当其被触摸时,会在用户触摸屏幕的位置绘制一个圆圈。但是,当我打电话时,mSurfaceHolder.lockCanvas()我得到了一个例外。每当画布锁定时,都会出现非法论点。示例代码发布在下面。

public class TapArea extends SurfaceView implements SurfaceHolder.Callback {
    private static final int TAP_RADIUS = 4;
    private boolean mLoaded = false;
    private Paint mTapPaint;
    private SurfaceHolder mSurfaceHolder;

    protected OnTouchListener mTouchEvent = new OnTouchListener() {
        @Override
        public boolean onTouch(View arg0, MotionEvent arg1) {
            if (!mLoaded)
                return false;

            Canvas c = null;
            c = mSurfaceHolder.lockCanvas();
            drawTap(c, arg1);

            return true;
        }
    };

    public TapArea(Context context, AttributeSet attrs) {
        super(context, attrs);

        this.setOnTouchListener(mTouchEvent);
        mHandler = new Handler();
        mSurfaceHolder = getHolder();
        mSurfaceHolder.addCallback(this);
        mTapPaint = new Paint();
    }

    public void drawTap(Canvas canvas, MotionEvent tap) {
        canvas.drawCircle(tap.getX(), tap.getY(), TAP_RADIUS, mTapPaint);
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
        // TODO Auto-generated method stub

    }

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
        // TODO Auto-generated method stub
        mLoaded = true;
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        // TODO Auto-generated method stub

    }
}

以下是我不断收到的错误日志:

01-17 00:19:44.703: E/Surface(9731): Surface::lock failed, already locked
01-17 00:19:44.796: E/SurfaceHolder(9731): Exception locking surface
01-17 00:19:44.796: E/SurfaceHolder(9731): java.lang.IllegalArgumentException
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.Surface.lockCanvasNative(Native Method)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.Surface.lockCanvas(Surface.java:314)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.SurfaceView$3.internalLockCanvas(SurfaceView.java:762)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.SurfaceView$3.lockCanvas(SurfaceView.java:741)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at com.frequency.FreqTapArea$2.onTouch(FreqTapArea.java:54)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.View.dispatchTouchEvent(View.java:3897)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:869)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:869)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:869)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1737)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1153)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.app.Activity.dispatchTouchEvent(Activity.java:2096)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1721)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2200)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1884)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.os.Handler.dispatchMessage(Handler.java:99)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.os.Looper.loop(Looper.java:130)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.app.ActivityThread.main(ActivityThread.java:3835)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at java.lang.reflect.Method.invokeNative(Native Method)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at java.lang.reflect.Method.invoke(Method.java:507)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
01-17 00:19:44.796: E/SurfaceHolder(9731):  at dalvik.system.NativeStart.main(Native Method)

帮助将不胜感激。


问题答案:

在画布上绘制后,需要将其解锁。正确的安全性是:

  1. 得到画布调用mSurfaceHolder.lockCanvas();
  2. 在画布上画画。
  3. 解锁调用mSurfaceHolder.unlockCanvasAndPost(c)的画布;

在您的代码中可能是:

public boolean onTouch(View arg0, MotionEvent arg1) {
        if (!mLoaded)
            return false;

        Canvas c = mSurfaceHolder.lockCanvas();
        drawTap(c, arg1);
        mSurfaceHolder.unlockCanvasAndPost(c);

        return true;
    }


 类似资料:
  • 问题内容: 我在这里思考:如果您有2个线程执行需要同步的FAST操作,那么非阻塞方法不是比阻塞/上下文切换方法更快/更好的方法吗? 非阻塞的意思是: while(true){如果(checkAndGetTheLock())中断;} 如果您有太多线程在锁中循环,我唯一想到的就是饥饿(CPU耗尽)。 如何平衡一种方法与另一种方法? 问题答案: 以下是 Java Concurrency in Pract

  • 问题内容: 我正在阅读《 实践Java并发 》一书。在第15章中,他们讨论了非阻塞算法和 比较交换 (CAS)方法。 据记载,CAS的性能比锁定方法好得多。 我想问一下已经使用这两个概念的人,并想听听您何时更喜欢这些概念中的哪一个? 真的那么快吗? 对我来说,锁的用法更加清晰,易于理解,甚至维护起来也更好 (如果我错了,请纠正我) 。我们是否应该真正专注于创建与CAS相关的并发代码,而不是锁定,以

  • 我看不出有什么区别。我读到了这篇文章:actual-use-of-lockinterruptbly-for-a-reentrantlock 想测试一下。代码如下: 这里是Inturrept班 控制台输出: 正如回答中提到的“这与常规锁()相同。但如果另一个线程中断,等待的线程lockInterruptbly()将抛出InterruptedException。”即使它是锁着的。lock()或lock

  • 锁定 Subversion的拷贝-修改-合并版本控制模型的关键是其合并算法,也就是如何处理多个用户修改同时修改一个文件产生冲突时的算法。Subversion本身只提供了一个这样的算法,其三方区别算法可以足够聪明的的行粒度的数据处理,Subversion也支持使用外置比较工具(“外置 diff3”一节中有描述),有一些可以做得非常好,或许可以提供以单词或字母粒度的算法。但是,这些工具的共同点是基于文

  • 问题内容: 输出是 线程1开始 线程1的内部演示 线程2开始 线程2的内部演示 由于,执行尚未结束。 我已经通过类的同一个实例来的两个类的构造函数和。 对in 的调用位于一个块中。 要在通话中是 没有 的块。 所以,当被执行时,由于块,的监视器应锁定,导致拒绝访问,以由所述。 但是,这没有发生。 预期的输出是 (输出在完成之前。) 因此,我的基本问题是: 即使 尚未完成 块, 如何成功执行? 问题

  • 我正在编写一个应用程序来管理或自定义Android设备的解锁屏幕。它的工作原理如下: 用户使用电源按钮锁定屏幕。 用户尝试解锁屏幕,从而再次按下电源按钮 我的活动弹出--屏幕仍然锁定 用户回答问题,如果答案正确,屏幕解锁 我已经为第三步创建了一个活动,并将以下代码添加到其方法中: 这工作正常,完全符合我的期望。我的问题是第四步。我已经搜索并找到了许多解决方案,但没有一个适合我。 如何以编程方式锁定