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:
@Override
public Object onRetainNonConfigurationInstance() {
//Save the thread
return backgroundThread;
}
to retrieve the object in the onCreate method:
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
…//Do something
backgroundThread = (Thread) getLastNonConfigurationInstance();
…//Do something again
}
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 *************************************************/
/******************************************************************************************/
/**
* The
Handler
*/
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";
/**
* The
ProgressBar
*/
private
ProgressBar progressBar;
/**
* The
way the progress bar increment
*/
private boolean reverse = false;
/**
* The
activity name
*/
private
String activityName;
/******************************************************************************************/
/** Managing the activity
**************************************************************************/
/******************************************************************************************/
/** Called when the
activity is first created. */
@Override
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)
*/
@Override
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)
// The List
No comments:
Post a Comment