The Canvas
is double- or triple- buffered and not erased between frames. When you call lock/unlock, you're switching between previously-rendered buffers.
If you move your if(userHealth<=0)
test into run()
and use it to avoid calling lock/unlock, you should get the desired effect.
For a much longer explanation about what's going on, see this post.
Update: I realized today that I'd omitted a detail (from the answer and ensuing comments). It doesn't change the answer but it may be useful to know.
The lockCanvas()
method takes an optional "dirty" rect that allows you to do partial updates. If you use this, and Surface
is able to keep track of the "front" buffer you just rendered, the system will copy the non-dirty contents of the front buffer to the back buffer as part of locking the Surface
(see copyBlt()
in Surface.cpp).
The system doesn't guarantee that this will work, which is why the "dirty" rect is an in-out parameter. If the front buffer isn't available to copy from, the lock method will just expand the dirty rect to cover the entire screen. In either case, your app is responsible for updating every pixel in the "dirty" rect; if you don't, you get the effects you observed.
This does mean that the Surface
is explicitly trying to be double-buffered when used with a Canvas
, which would explain why you're seeing two frames alternating rather than three even though SurfaceView
is generally triple-buffered. (Which is the thing that has been nagging at me since I wrote this up.) It's also possible to be double-buffered if you're just not generating frames fast enough to require triple-buffering.