Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android program flow control in presence of startActivityForResult call

The program in question, when run on Android, controls slave Bluetooth (BT) devices. It has few buttons which enable different functions of the peer devices.

Bluetooth is not enabled by default on the Android device, and the connection is established for short periods after button(s) click.

So, the flow after each button click is:

  1. ensure BT enabled (startActivityForResult() with BT enable intent if not)
  2. connect to the remote device
  3. enable some function of the remote device
  4. disconnect from the device

My issue is that if BT is not enabled, then a call to startActivityForResult() in #1 "breaks" the program flow. Later, when onActivityResult() is called, I want to resume the flow from the point where it was "breaked".

For that purpose I defined additional member field and few constants and used them in onActivityResult():

private int mRerunMethodIndex = 0;
private static final int RERUN_METHOD1 = 1;
private static final inr RERUN_METHOD2 = 2;
...
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case REQUEST_ENABLE_BT:
            if (resultCode == Activity.RESULT_OK) {
                int rerunMethodIndex = mRerunMethodIndex;
                mRerunMethodIndex = 0;
                switch (rerunMethodIndex ) {
                    case (RERUN_METHOD1):
                        method1();
                        break;
                    case (RERUN_METHOD2):
                        method2();
                        break;
                    // ... the same for other cases
                }
            }
            break;    
        default:
            break;
    }
}

Now, one more complication: onActivityResult() will be called before activity's onResume(). This will matter if any of the methodX() need to alter views hierarchy. In my case these methods replace some Fragments, and if this operation is executed from onActivityResult() then exception is thrown.

In order to resolve this additional issue, the ugly switch from onActivityResult() migrates to onPostResume().

The approach described above works, but it is one of the ugliest pieces of code I've ever written: methodX() "registers" itself for "rerun" by assigning RERUN_METHOD_X constant to mRerunMethodIndex, onActivityResults() sets some "rerun flag" after BT is enabled, onPostResume() checks the flag, clears this flag, clears mRerunMethodIndex and reruns the appropriate methodX().

Is there a more elegant approach (preferably confined to 1 or 2 methods)?

like image 370
Vasiliy Avatar asked Jan 15 '15 22:01

Vasiliy


1 Answers

You could use runnable to organize your workflow without using step constants. For example:

public void Runnable mMethod1 = new Runnable() {
    public void run() {
        // your code for method 1
    }
}

public void Runnable mMethod2 = new Runnable() {
    public void run() {
        // your code for method 2
    }
}

public void Runnable mMethod3 = new Runnable() {
    public void run() {
        // your code for method 3
    }
}

private void startMethod(Runnable method) {
    mCurrentMethod = method;
    method.run();
}

...

public vond onPostResume() {
    if (mCurrentMethod != null) {
        mCurrentMethod.run();
        mCurrentMethod = null;
    }
}
like image 144
Médéric Avatar answered Oct 29 '22 03:10

Médéric