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" />

アクティビティは View through を設定します

setContentView(R.layout.activity_main);
4

2 に答える 2

1

できません。にCanvas渡されたView.onDraw()は、メイン スレッド (UI スレッド) からのみ使用する必要があります。 (任意のスレッドからSurfaceViewを使用できます)、 (同じもの) を使用するか、中間ビットマップにレンダリングする必要があります。CanvasTextureView

于 2013-08-13T17:29:43.793 に答える
1

この場合、UI スレッドで描画を行う必要があります。もう 1 つのことは、描画は onDraw() 内でのみ安全に実行できると確信しているということです。長いループを通過するため、コードが遅くなります。

そのため、代わりに、そのイメージをビットマップに生成する別のスレッドを作成します。次に、そのビットマップを UI スレッドと共有すると、実際にそのビットマップをキャンバスに描画できます。ロックステップ方式でジョブを取得するには、一連の wait() および notify() 呼び出しが必要になる場合がありますが、これは別のスレッドで行うにはまだ遅すぎる可能性があります。この画像を本当にダイナミックにしたい場合は、次のいずれかを行います

1) 数フレームごとに UI のビットマップのみを更新しますが、他のスレッドで画像を生成することはできます

2)何度もループする必要のない画像を生成するための別の方法を使用します

ベスト プラクティスでは、onDraw() は、集中的な作業を行わずに、可能な限り高速にする必要があります。

于 2013-08-13T17:30:33.907 に答える