0

A similar question exists here but does not seem applicable to my problem: Android SurfaceHolder.unlockCanvasAndPost() does not cause redraw

See the end for the problem description, but first...

My Code

I have a very simple Activity:

...
void onCreate(...) {
    setContentView(new MySurfaceView(this))
}
...

MySurfaceView.java:

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    private MySurfaceViewThread task = null;
    private SurfaceHolder holder = null;

    public MySurfaceView(Context ctx) {
        super(ctx);
        holder = getHolder();
        holder.addCallback(this);
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        this.holder = holder; // EDIT per user2635653's answer
    }

    public void surfaceCreated(SurfaceHolder holder) {
        this.holder = holder; // EDIT per user2635653's answer
        task = new MySurfaceViewThread(holder);
        task.run();
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        if (task != null)
            task.postStop();
    }
}

MySurfaceViewThread.java:

public class MySurfaceViewThread extends Thread {
    private SurfaceHolder holder = null;
    private int blue = 235;
    private volatile boolean run = true;

    public MySurfaceViewThread(SurfaceHolder h) {
        holder = h;
    }

    @Override
    public void run() {
        while(run) {
            if (holder.getSurface().isValid()) {
                Canvas c = holder.lockCanvas();
                if ((blue += 10) > 255)
                    blue = 0;
                c.drawColor(Color.argb(255, 0, 0, blue));
                holder.unlockCanvasAndPost(c);

                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void postStop() {
        run = false;
    }
}

The Problem

The surface view never updates, even though i drawColor repeatedly. No exceptions are thrown, and the lockCanvas and unlockCanvasAndPost get called. However, the activity remains black after launching the app.

I noticed some interesting behavior: if I limit the number of times the while loop runs, then after the Thread finishes, the surface view will finally draw.

I know I could copy-and-paste some working code, but my objective in asking this question is to gain a better understanding of why this doesn't work, and learn something about the Android SurfaceView.

Community
  • 1
  • 1
Jonathan Apodaca
  • 5,458
  • 6
  • 30
  • 41
  • I just came across this same behaviour and cannot find the issue.. I'm calling the thread object `start()`method (as you pointed out it was the source of your problems), but `unlockCanvasAndPost()` still doesn't refresh the screen although the drawing instructions in my drawing method are run... Same code structure than yours, Activity , SurfaceView object and Thread object inside the SurfaceView one which gets started when the `onSurfaceCreated` method fires.... I'm getting desperate :P EDIT: I'm gonna try this: http://stackoverflow.com/a/3867452/3736964 – JorgeGRC Feb 27 '15 at 10:26

2 Answers2

1

Try deleting holder = getHolder(); from your constructor. And add this.holder = holder; to your public void surfaceCreated(SurfaceHolder holder) Method.

wanpanman
  • 378
  • 3
  • 10
  • I need the `holder = getHolder()` in the ctor for the `holder.addCallback(this)`, but I did add `this.holder = holder` to `surfaceCreated(...)` and `surfaceChanged(...)`... it still waits to update the `SurfaceView` until after the Thread finishes execution. (I've updated my answer to reflect how I incorporated this suggestion) – Jonathan Apodaca Jul 30 '13 at 20:44
-1

I can't believe it: it came down to one line (isn't that the way it always is?):

task.run(); // NO!...runs the code synchronously

versus:

task.start(); // starts running the code in a separate thread, as expected.
Jonathan Apodaca
  • 5,458
  • 6
  • 30
  • 41