0

下面的程序画了一点云

云

在用户触摸的位置。

如果你用 替换/*A*////*A*/它运行良好。

但它是缓慢的。因此(没有注释掉/*A*/s)绘图是在一个单独的线程上完成的。为了保持流畅的交互,当用户移动指针时线程会被中断。

您将如何修改此代码以正确绘制单独的线程?

public class MyView extends View {
/*A*/ protected MyDrawThread myDrawThread;
    protected float x, y;
    protected Paint paint = new Paint();

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint.setAntiAlias(true);
/*A*/   myDrawThread = new MyDrawThread();
    }

    @Override protected void onDraw(Canvas canvas)
    {
/*A*/        if( myDrawThread.isAlive() )
/*A*/            myDrawThread.interrupt();
/*A*/
/*A*/        myDrawThread.setCanvas( canvas );
/*A*/        myDrawThread.start();
/*A*/    }
/*A*/
/*A*/    class MyDrawThread extends Thread {
/*A*/        private Canvas canvas;
/*A*/
/*A*/        public MyDrawThread() {
/*A*/            super();
/*A*/        }
/*A*/        public void setCanvas( Canvas cnvs ) {
/*A*/            canvas = cnvs;
/*A*/        }
/*A*/        public void run()
/*A*/        {
            for(int i=0;i<10000;++i) {
                double angle = (double) (Math.random() * 2.0 * Math.PI);
                float distance = (float) (Math.random() * getWidth()/25.0f);
                float dx = (float) (distance*Math.cos(angle));
                float dy = (float) (distance*Math.sin(angle));
                canvas.drawCircle(x+dx, y+dy, 0.1f, paint);
            }
/*A*/   }
    }
    @Override public boolean onTouchEvent(MotionEvent event) {
        x = event.getX();
        y = event.getY();
        invalidate();
        return true;
    }
}

布局activity_main仅包括

<.MyView
    android:id="@+id/myView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

并且活动设置视图通过

setContentView(R.layout.activity_main);
4

2 回答 2

1

你不能。Canvas传递的 to只能View.onDraw()从主线程(UI 线程)使用。您应该使用 a SurfaceView(允许您使用Canvas来自任意线程的 a)、a TextureView(相同的东西)或渲染到中间位图。

于 2013-08-13T17:29:43.793 回答
1

在这种情况下,必须在 UI 线程上进行绘图。另一件事是我很确定绘图只能在 onDraw() 内部安全地完成。你的代码很慢,因为你经历了一个很长的循环。

因此,您将创建一个单独的线程,将该图像生成为位图。然后与 UI 线程共享该位图,您实际上可以将该位图绘制到画布上。您可能需要一组 wait() 和 notify() 调用才能以锁步方式获取作业,但是,在另一个线程上完成这可能仍然太慢。如果你真的想让这张图片变得动态,我要么

1) 仅每隔几帧更新UI上的位图,但您仍然可以使用其他线程生成图像

2)使用另一种方法来生成不必循环这么多次的图像

在最佳实践中,您的 onDraw() 应该尽可能快,而不是做任何密集的工作。

于 2013-08-13T17:30:33.907 回答