You said ... "I use surfaceView, which, as I understand it, uses a separate stream for rendering (separately from the user interface stream) - so I have 3 threads"
It looks like you are assuming that by expanding SurfaceView, you are automatically provided with another main thread for the surface, which is separate from the user interface thread. I believe that this is not so.
From an Android developer link for SurfaceView: "One of the goals of this class is to provide a surface on which a secondary stream can be displayed on the screen." The keyword may be. You still have to create a separate stream yourself, SurfaceView just makes it easy to draw on canvas in a separate stream.
If you take LunarLander as an example, it has only two threads: the user interface thread and the manually created “LunarThread”, in which the physics is updated, and the canvas is drawn (via SurfaceHolder.lockCanvas ()) as quickly as possible, regardless of user interface thread.
source share