Question

Can some please suggest an alternative to using two different handlers in the one activity, or let me know that this method is OK?

Details: I'm in the process of developing some code for use with Microchips ADK Android starter kit. Everything is running smoothly, however, I have an issue where there are two different handlers running in the code, it works but I have noticed that it is not recommended. The first handler I use to create a time delay, and use the post command to launch the result. The second handler is used in Microchip's sample code that they supplied to communicate with their USB accessory framework files. I prefer to only tinker with the Microchip code rather than rewriting it. Similar code:

public class MainActivity extends Activity 
{   ...
    final Handler mHandler = new Handler(); // handler for startTimeDelay
    ...
    protected void onCreate(Bundle savedInstanceState)
    {   super.onCreate(savedInstanceState);
        ...
        Button btnSetTimeDelay = (Button) findViewById(R.id.btnChangeTimeDelay);
        btnSetTimeDelay.setOnClickListener
            (   new View.OnClickListener() 
                {   public void onClick(View v) 
                    {
                        setBackgroundColorLinearLayout(color.holo_red_dark); //red background
                        displayLockIsOpen(false);   // display closed lock message
                        startTimeDelay();   // wait to open the lock
                    }
                }
            );
    } // onCreate
    ...
    final Runnable mUpdateResults = new Runnable()
    {   public void run()
        {   setBackgroundColorLinearLayout(color.holo_green_dark); //green background
            displayLockIsOpen(true);    // display open lock message
        }
    };

    protected void startTimeDelay()
    {   Thread t = new Thread()
        {   @override
            public void run()
            {   SystemClock.sleep(global_delay);
                mHandler.post(mUpdateResults);  // run mUpdateResults code
            };
        };
        t.start();
    } // startTimeDelay

    // USB accessory handler from Microchip, for ADK
    private Handler handler = new Handler()
    {   @override
        public void handleMessage(Message msg)
        {   
            ...
            switch(msg.what)
            {   case USBAccessoryWhat:
                ...lots of code here from Microchip
            } // switch msg.what
        } // handleMessage
    }; // Handler
} // MainActivity 
Was it helpful?

Solution

You can create a single Handler itself both for startTimeDelay and USB accessory.

From the code of android.

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

Its says when you have a callback(Runnable) it will call handleCallback which will call your Runnable.run Method, else handleMessage will be called.

So you can have a single handler.

OTHER TIPS

Thanks Vivek for your answer. I've also found that I can remove the line:

final Handler mHandler = new Handler(); // handler for startTimeDelay

and rename

mHandler.post(mUpdateResults); // run mUpdateResults code

to

handler.post(mUpdateResults); // run mUpdateResults code

The fact that Microchip's code overrides handleMessage has no effect on the .post method and it works normally. Giving me the below code.

public class MainActivity extends Activity 
{   ...
// final Handler mHandler = new Handler();  // handler for startTimeDelay, not needed
    ...
    protected void onCreate(Bundle savedInstanceState)
    {   super.onCreate(savedInstanceState);
        ...
        Button btnSetTimeDelay = (Button) findViewById(R.id.btnChangeTimeDelay);
        btnSetTimeDelay.setOnClickListener
            (   new View.OnClickListener() 
                {   public void onClick(View v) 
                    {
                        setBackgroundColorLinearLayout(color.holo_red_dark); //red background
                        displayLockIsOpen(false);   // display closed lock message
                        startTimeDelay();   // wait to close the lock
                    }
                }
            );
    } // onCreate
    ...
    final Runnable mUpdateResults = new Runnable()
    {   public void run()
        {   setBackgroundColorLinearLayout(color.holo_green_dark); //green background
            displayLockIsOpen(true);    // display open lock message
        }
    };

    protected void startTimeDelay()
    {   Thread t = new Thread()
        {   @override
            public void run()
            {   SystemClock.sleep(global_delay);
                handler.post(mUpdateResults);   // run mUpdateResults code
                // changed from mHandler to handler, defined below
            };
        };
        t.start();
    } // startTimeDelay

    // USB accessory handler from Microchip, for ADK
    private Handler handler = new Handler()
    {   @override
        public void handleMessage(Message msg)
        {   
            ...
            switch(msg.what)
            {   case USBAccessoryWhat:
                ...lots of code here from Microchip
            } // switch msg.what
        } // handleMessage
    }; // Handler
} // MainActivity

For me this was simple as I didn't need to rewrite any code, but I'm not sure whether its better practise or not. Your code would atleast direct the code reader to one location for the handler whereas in my version the running of mUpdateResults is not explicitly visible in the handler routine.

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