Replacing View with SurfaceView to draw on other than the UI Thread

僤鯓⒐⒋嵵緔 提交于 2019-12-11 03:45:27

问题


The following program does not work unless the line while (!done) (and the closing bracket) are uncommented.

Do you understand why? Why is it not possible to ask the thread to run the drawing code just once?

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    private SurfaceHolder holder;
    private MyThread myThread;
    private boolean hasSurface;

    protected float x, y;
    protected Paint paint;

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

        holder = getHolder();
        holder.addCallback(this);
        hasSurface = false;

        paint = new Paint(Paint.ANTI_ALIAS_FLAG|Paint.SUBPIXEL_TEXT_FLAG);
        paint.setColor(Color.RED);
    }

    public void resume() {
        if (myThread == null) {
            myThread = new MyThread();

            if (hasSurface == true)
                myThread.start();
        }
    }

    public void pause() {
        if (myThread != null) {
            myThread.requestExitAndWait();
            myThread = null;
        }
    }

    public void surfaceCreated(SurfaceHolder holder) {
        hasSurface = true;
        if (myThread != null)
            myThread.start();
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        hasSurface = false;
        pause();
    }

    public void surfaceChanged(SurfaceHolder holder, int format,
                               int w, int h) {
        if (myThread != null)
            myThread.onWindowResize(w, h);
    }

    @Override public boolean onTouchEvent(MotionEvent event) {
        x = event.getX();
        y = event.getY();
        postInvalidate();
        return true;
    }

    //************************************************
    class MyThread extends Thread {
        private int width, height;

        private boolean done;

        MyThread() {
            super();
            done = false;
        }

        @Override
        public void run() {
            SurfaceHolder surfaceHolder = holder;

            // while (!done) { --- We wish to update just once.

                Canvas canvas = surfaceHolder.lockCanvas();

                canvas.drawARGB(255, 0, 0, 128);
                canvas.drawCircle(x, y, 5.0f, paint);

                surfaceHolder.unlockCanvasAndPost(canvas);
                }
            // }
        }

        public void requestExitAndWait() {
            done = true;
            try {
                join();
            } catch (InterruptedException ex) { }
        }

        public void onWindowResize(int w, int h) {
            width = w;
            height = h;
        }
    }
}

Here is the activity:

public class MyActivity extends Activity {

    MySurfaceView mySurfaceView;

    @Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mySurfaceView = (MySurfaceView) findViewById(R.id.mySurfaceView);
    }

    @Override protected void onResume() {
        super.onResume();
        mySurfaceView.resume();
    }

    @Override protected void onPause() {
        super.onPause();
        mySurfaceView.pause();
    }
}

.. and here is the layout

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent">
   <.MySurfaceView
       android:id="@+id/mySurfaceView"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"/>
</FrameLayout>

回答1:


There you go

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    ...

    class MyThread extends Thread {

        boolean update = false;

        @Override
        public void run() {
            SurfaceHolder surfaceHolder = holder;

            while (!done) {

                if(update) {
                    Canvas canvas = surfaceHolder.lockCanvas();

                    canvas.drawARGB(255, 0, 0, 128);
                    canvas.drawCircle(x, y, 5.0f, paint);

                    surfaceHolder.unlockCanvasAndPost(canvas);
                    update = false;
                }
            }
        }
    }

    public void requestUpdate() {
        update = true;
    }
}

and whenever something is changed, just call requestUpdate();



来源:https://stackoverflow.com/questions/18240420/replacing-view-with-surfaceview-to-draw-on-other-than-the-ui-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!