问题
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