Question

can someone explain what what is going on here for which thread is being blocked? the thread object here is used for canvas and drawing graphics, the join() method is called on this graphics thread so it will continue to finish. while the other thread is blocked and waiting. which thread is this?

if the surfaceView class is running on the main UI thread than the UI will be blocked waiting for the graphics thread to finish. this does not make sense. so the other explanation would be for there to be three separate threads here. the main UI thread, the graphics thread where join() is being called on, and a third thread for surface view that is getting blocked while the graphics thread finishes

is there in fact three threads running, and the UI thread is not the one being blocked?

nowhere in my code did I start a new thread for SurfaceView. I only instantiated a SurfaceView object.

as this code is written it looks like the main UI thread is blocked waiting for the graphics thread to finish.

If the SurfaceView object is instantiated inside of a thread or AsyncTask then it would look more clear.

// this code is located inside of the SurfaceView class

@Override
public void surfaceCreated(SurfaceHolder holder) {
    // can also put this code in surfaceChanged
    running = true;
    thread = new Thread(surfaceRunnable);
    thread.start();

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    running = false;
    boolean retry = true;
    while(retry) {
        try {
        thread.join();
        retry = false;
        } catch( InterruptedException e) {

        }
    }
Was it helpful?

Solution

The thread that is blocked is the UI thread. Proving this with a debugger is a good idea. You can confirm this by viewing the source code of SurfaceView.java (if in Eclipse, hit F3 while the cursor is on the text SurfaceView). In particular:

The callbacks such as surfaceDestroyed() are called from SurfaceView.updateWindow():

private void updateWindow(boolean force, boolean redrawNeeded) {
    ...
    callbacks = getSurfaceCallbacks();
    for (SurfaceHolder.Callback c : callbacks) {
        c.surfaceDestroyed(mSurfaceHolder);
    }

updateWindow() is called from the anonymous class derived from Handler and assigned to mHandler:

final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case KEEP_SCREEN_ON_MSG: {
                setKeepScreenOn(msg.arg1 != 0);
            } break;
            case GET_NEW_SURFACE_MSG: {
                handleGetNewSurface();
            } break;
            case UPDATE_WINDOW_MSG: {
                updateWindow(false, false);
            } break;
        }
    }
};

Note that this mHandler object is constructed when the SurfaceView object is constructed, which happens on the UI thread. And note that the Handler constructor binds the Handler to the Looper associated with the current thread (the UI thread). So handleMesssage() runs on that Looper which is the UI thread's Looper. Thus, updateWindow() is called on the UI thread.

updateWindow() is also called several other times in the file and most of the time it is easy to deduce that it is being called from the UI thread.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top