0

I am beginner to multithreading in Java and in my Android application, i have that SurfaceView on wich am drawing a circle randomlly but i want to be able to pause that drawing by pressing the screen (ACTION_DOWN) and resume it the next time i press it again :

     import android.content.Context;

     import android.content.Intent;

     import android.graphics.Canvas;

     import android.graphics.Color;

     import android.graphics.Paint;

     import android.view.MotionEvent;

     import android.view.SurfaceHolder;

     import android.view.SurfaceView;


     public class GameView extends SurfaceView /**/implements SurfaceHolder.Callback { 


private float x = 100;
private float y = 100;
private int radius = 20;
private Paint paint;
private SurfaceHolder mSurfaceHolder;
private DrawingThread mThread;
private Context myContext;

public GameView(Context context) {
    super(context);
    this.myContext = context;
    setWillNotDraw(false);
    paint = new Paint(); 
    /**/
    paint.setAntiAlias(true); 
    paint.setColor(Color.GREEN);
    paint.setStyle(Paint.Style.STROKE);
    paint.setTextAlign(Paint.Align.LEFT);
    mSurfaceHolder = getHolder();
    mSurfaceHolder.addCallback(this);
    //paint.setTextSize(15);
}


public void onDraw(Canvas canvas){

    canvas.drawCircle(x, y, radius, paint);
}
/**/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    // TODO Auto-generated method stub

}

@Override
public void surfaceCreated(SurfaceHolder holder) {


        mThread = new DrawingThread(mSurfaceHolder, myContext);
        mThread.mRun = true;
        mThread.start();

}

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

}



public synchronized boolean onTouchEvent(MotionEvent event) { 

    int eventaction = event.getAction();
    int X = (int)event.getX();
    int Y = (int)event.getY();



    switch (eventaction ) {
        case MotionEvent.ACTION_DOWN:

                this.mThread.canPause = !this.mThread.canPause;
            synchronized(this.mSurfaceHolder){
                if(this.mThread.canPause){
                    this.mSurfaceHolder.notify();
                }
            }


        break;
        case MotionEvent.ACTION_MOVE:
        break;
        case MotionEvent.ACTION_UP:

        break;
    }

    invalidate();
    return true;
       }
public final class DrawingThread extends Thread {



    public boolean canPause = false;

    boolean mRun;

    Canvas mcanvas;

    SurfaceHolder surfaceHolder;

    Context context;



    public DrawingThread(SurfaceHolder sholder, Context ctx)

    {

    surfaceHolder = sholder;

    context = ctx;

    mRun = false;
    }



    void setRunning(boolean bRun)

    {

    mRun = bRun;

    }


    boolean keepDrawing = true;



    @Override
    public void run() {
        while (keepDrawing) {
                Canvas canvas = null;
                try {

                         canvas = mSurfaceHolder.lockCanvas();
                        synchronized (mSurfaceHolder) {

                            while(canPause){
                                try {

                                                   mSurfaceHolder.wait();
                                }                           catch(InterruptedException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                            }
                            waitThreaed();
                            draw(canvas);
                        }
                } 
                catch(Exception e){

                }
                finally {
                        if (canvas != null)
                                                                   mSurfaceHolder.unlockCanvasAndPost(canvas);
                    }


       }
}

    public void waitThreaed() {

         try {
                    x = (float) (getWidth()*Math.random());
                    y = (float) (getHeight()*Math.random());
                    this.sleep(1000);
                    postInvalidate();
            } catch (InterruptedException e) {

            }
    }
    }

   }

In fact with that code the drawing can be paused but can not be resumed

GB11
  • 175
  • 1
  • 18
  • have you tried using Thread.sleep() instead of Thread.wait()? – panini Feb 11 '14 at 00:05
  • Oh yes, i have , but like i said i want to manually be able to pause and resume it not temporarilly with some timeout passed to sleep as argument, or am i wrong in that ? – GB11 Feb 11 '14 at 00:08
  • well you already have your while(canPause) loop, why not put a Thread.sleep(100) in there instead of the Thread.wait()? I think that should work how you want it to – panini Feb 11 '14 at 00:11
  • I tried it with Thread.sleep(100) and it can pause but can not be resumed until that timeout expires wich is not my objectif while i want to resume it manullay as i pause it manually too – GB11 Feb 11 '14 at 00:17

1 Answers1

0

In order to call wait() you must have synchronized on the object you are waiting on.

See this question for a discussion of that: Why must wait() always be in synchronized block

Community
  • 1
  • 1
Nick Palmer
  • 2,589
  • 1
  • 25
  • 34
  • Yeah thank you but can you please have a look to my code to check weather i have the right synchronized object or not – GB11 Feb 11 '14 at 05:02
  • You don't or you wouldn't be getting the error. In the action down handler you are synchronizing on `this.mSurfaceHolder` but calling notify() on `this`. If you are going to synchronize on `this.mSurfaceHolder` then do `this.mSurfaceHolder.notify()`. In the on Draw you are calling `wait()` on `this` without synchronizing at all. You need to do `synchronized (this.mSurfaceHolder) { this.mSurfaceHolder.wait() }` – Nick Palmer Feb 11 '14 at 16:36
  • thank you. i have updated my code above with your indication and the drawing can be paused but can not be resumed – GB11 Feb 12 '14 at 05:27
  • To resume you need to call notify() on the mSurfaceHolder to cause the wait to finish. Please educate yourself on how synchronization, wait, notify and notifyAll work in java. This is a good start: http://stackoverflow.com/questions/2536692/a-simple-scenario-using-wait-and-notify-in-java – Nick Palmer Feb 12 '14 at 09:52