BluetoothChat synchronized onResume Activity lifec

2019-06-21 08:08发布

问题:

I'm studying right now the bluetooth Android API, and I ran into the BluetoothChat example. http://developer.android.com/resources/samples/BluetoothChat/index.html

It contains many errors, first of all the simple fact that it uses API 11 but manifest does not force this minimum API.

Other interesting thing is the use of synchronized keyword on Activity lifecycle methods, like on onResume:

    @Override
public synchronized void onResume() {
    super.onResume();
    if(D) Log.e(TAG, "+ ON RESUME +");

    // Performing this check in onResume() covers the case in which BT was
    // not enabled during onStart(), so we were paused to enable it...
    // onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
    if (mChatService != null) {
        // Only if the state is STATE_NONE, do we know that we haven't started already
        if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
          // Start the Bluetooth chat services
          mChatService.start();
        }
    }
}

Why this keyword is used there? Is there any reasonable explanation, or simply the one who wrote the code didn't know that onResume will be called always by the same thread? Or I miss something?

Thank you in advance!

回答1:

This seems to be a pretty old question, but here's what I think may be going on:

My guess is that it wants to be careful about when "dialogs" return. The BluetoothChat example uses dialogs (as well as an overlay dialog-like activity) for enabling Bluetooth, enabling discovery, and initiating pairing/connections.

I don't know this for sure but I suspect there was a bug where different threads were returning to the main Activity and caused confusion as to how to handle onResume.

What they probably should have done is synchronize a block on an object and used flags to determine the state. That way the intention, state and functionality are more clear -- and the app knows what it should do in onResume;

something like this maybe:

//class fields    
private Object myLockObj = new Object();
private boolean isPausedForPairing = false;

public void onResume()
{
    super.onResume();

    synchronized (myLockObj)
    {
        if (isPausedForPairing)
        {
            //handle a "pairing" onResume
        }
    }
}

However, due to it being an example app, they may have decided to go with something more simple. Example apps don't always follow convention because the idea is to demonstrate the particular code needed for the example. Sometimes following convention might add a lot of "distracting" code. Whether or not you agree with that is up to you though.