Hello again,
To continue with the issue of Handler and activity's life cycle, there is a solution, advocated by some, that is to use the public method Object onRetainNonConfigurationInstance () to return a pointer to an object in the activity.
Uh, let me explain, when your activity is to be destroyed and immediately recreates the method onRetainNonConfigurationInstance can send an object from the instance of the dying activity to the instance of new activity.
Example adapted to our problem:
public Object onRetainNonConfigurationInstance() {
//Save the thread
return backgroundThread;
to retrieve the object in the onCreate method:
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
backgroundThread = (Thread) getLastNonConfigurationInstance();
It is clear that with this method everything seems solved (at least for the change in orientation of the device). And yes, BUT NOT!!!, it's a serious mistake to think that. Indeed, what happens if your activity is killed (without being recreated immediately)? Well, then your thread is an orphan, your handler and your activity become ghosts (because the garbage collector detects them as used). And here, again, Darth Vader mocks.
The solution, and yes, there is one, is somewhat more complex than that. We must re-implement an atomic boolean to kill the thread if your activity is not restarted immediately.
And then, well, I invite you to get the tutorials that I dropped on Android2EE section Example/Tutorials/Handler's Tutorials. I give you 3 tutorials, one with the Atomic booleans, one with the onRetainNonConfigurationInstance instance and the last is a demonstration of the memory leaks.
But if your want the code, here it is:
The code of the activity:
public class
HandlerActivityBindingThreadTutoActivity extends
Activity {
/******************************************************************************************/
/** Managing the
Handler and the Thread *************************************************/
/******************************************************************************************/
private
Handler handler;
* The
thread that update the progressbar
Thread backgroundThread;
* The
runnable that have atomic booleans to be managed (and killed)
ManagedRunnable runnable;
/******************************************************************************************/
/** Others attributes
**************************************************************************/
/******************************************************************************************/
* The
string for the log
private final static
String TAG = "HandlerActivityBindingThreadTutoActivity";
private
ProgressBar progressBar;
* The
way the progress bar increment
private boolean reverse = false;
private
String activityName;
/******************************************************************************************/
/** Managing the activity
**************************************************************************/
/******************************************************************************************/
/** Called when the
activity is first created. */
public void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
backgroundThread =
(Thread) getLastNonConfigurationInstance();
setContentView(R.layout.main);
// Instantiate the
progress bar
progressBar =
(ProgressBar) findViewById(R.id.progressbar);
progressBar.setMax(100);
// use a random double to
give a name to the thread, the handler and the activity
double
randomD = Math.random();
final int
randomName = (int) (randomD * 100);
activityName = "Activity" +
randomName;
Log.e(TAG, "The
activity," + activityName + " is created");
// handler definition
handler = new
Handler() {
*
The handler name
String handlerName = "HandlerName" +
randomName;
*
(non-Javadoc)
*
@see android.os.Handler#handleMessage(android.os.Message)
public void
handleMessage(Message msg) {
super.handleMessage(msg);
// retrieve the calling
thread's name
int
threadId = (Integer) msg.getData().get("ThreadId");
Log.e(TAG, "The
handler," + handlerName + " receives a message
from the thread n°" + threadId);
// Launch treatment
updateProgress();
// Check if the thread is
already running (if the activity have been destroyed and recreated
// immediately after your
thread should be alive)