I created a Thread inside an Activity. At first, i thought that when onDestroy() is called on the Activity, then the thread will be killed also. But i was wrong. The Thread still continued running.
So i decided to cancel the thread inside the onDestroy() method. Everything works fine.
But there's 1 problem : onDestroy() is not guaranteed to be called. For example : the Activity is killed abruptly by the OS.
So what's the best thing to do in this case ? Thanks.
You should do everything related to cleanup in onPause(). You're correct that onDestroy() won't always be called, but onPause() is always called when activity moves to background or gets killed. But be careful to make your code in this method really lightweight, because an activity can't go to the background until this method returns.
I would propose to place Thread killing in Application onTerminate method
public class MyApplication extends Application
{
MyThread myThread;
#Override
public void onCreate()
{
super.onCreate();
myThread=new MyThread();
myThread.start();
}
#Override
public void onTerminate ()
{
super.onTerminate();
myThread.interrupt();
}
}
Be sure to declare MyApplication in AndroidManifest.xml
Related
I have an activity which has a button. Clicking on the button will start an asynctask and shows a progress loader on the activity.
This asynctask has some things to do but before that it has to make sure all the IntentServices of the app are finished handling intents from their queue.
I approached this problem by creating a lock object as below.
public class Lock{
private boolean isLocked = false;
public synchronized void lock()
throws InterruptedException{
while(isLocked){
wait();
}
isLocked = true;
}
public synchronized void unlock(){
isLocked = false;
notify();
}
}
An intent Service which is doing something will create an instance of Lock. It holds the lock in a public static field so that others can access it. It will call lock on the object above in onCreate() and will call unlock in onDestroy(). The asynctask will call lock on the same Lock object.
The expectation here is that my asynctask will wait till unlock() is called on the Lock object in onDestroy() of the service.
But the problem I am facing is that onDestroy() is never called on the IntentService. Android throws anr as ANR in <pkg> Reason: Executing service.
Can someone point out the problem in my understanding and implementation?
I want to stop my thread when my app closes. Does any one know how can I do this?
public class ControlApplication extends Application
{
private static final String TAG=ControlApplication.class.getName();
private Waiter waiter; //Thread which controls idle time
private MySharedPrefrences prefs;
// only lazy initializations here!
#Override
public void onCreate()
{
super.onCreate();
Log.d(TAG, "Starting application" + this.toString());
Context ctx=getApplicationContext();
waiter=new Waiter(1*60*1000,ctx);//(1*60*1000); //1 mins
prefs=new MySharedPrefrences(this);
// start();
}
#Override
public void onTerminate() {
super.onTerminate();
Log.d(TAG,"App terminated");
prefs.SetLastVisitedActivity("");
waiter.stopThread();
waiter.loginUpdate(false);
}
}
I want to call some methods when app terminates but I can't seem to get it working. Any suggestion please?
Try calling super.onTerminate(); after stopping the thread, i.e.,
#Override
public void onTerminate() {
Log.d(TAG,"App terminated");
prefs.SetLastVisitedActivity("");
waiter.stopThread();
waiter.loginUpdate(false);
super.onTerminate();
}
Update: onTerminate will never work on a device. http://developer.android.com/reference/android/app/Application.html#onTerminate%28%29
This method is for use in emulated process environments. It will never be called on a >production Android device, where processes are removed by simply killing them; no user code >(including this callback) is executed when doing so.
So your best bet is to create a base activity and let all other activities extend it. You can use onPause() of an Activity but if the app is terminated then there is no guarantee unless you call finish().
Update: As Nasir said in one of the comments, using onPause is not a good idea.
If your application has only one entry point then in your home/first activity override onDestroy() method, and from that method stop the thread.
I'm wondering if I can rely on a task which is executing in a separate non UI thread if I'm leaving an Activity. Looking on example below I can see the Runnable in a separate Thread is executing even if I'm on another Activity. But when would it be killed?
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
runTask();
startActivity(new Intent(this, SecondActivity.class));
}
private void runTask() {
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
Log.i("Dev", "here I am");
SystemClock.sleep(1000);
}
}
}).start();
}
}
The java.lang.Thread is not tied to the Android UI component lifecycle, so just like in a normal JVM it will keep going until its run() method returns... unless Android terminates your entire application process before that happens, which it can do if you app is in the background and another app needs the RAM.
Incidentally, because the thread is not tied to the UI component lifecycle, you cannot simply call into another UI component from that thread. You'll have to post to a Handler or issue a broadcast or something if you want to get back to the UI, but you may already know that.
Finally, in your sample code, the Thread instance (through the anonymous Runnable) will keep the enclosing Activity class from being garbage collected, so you may want to re-think that construct.
If you want to do background work that's not tied to any single Activity, you're generally better off modelling it as an IntentService.
you can call Interrupt() that will post a interrupt request for your thread.
http://developer.android.com/reference/java/lang/Thread.html
I just need to stop a thread which was created in previous run time of the same application. This is the scenario. I'm retrieving data from database for the notification using thread in background, But when I start that application again, number of threads are increasing. I need to stop this. I think its better to stop the background running thread in onCreate() method of the application's main class. But noway to do it. Please help me on this thing as soon as possible.
Thanks and Best Regards,
Shehan.
Keep a static reference to the running Thread in your activity class. Inside your thread you need to have a boolean variable you can set or a method you can call that will cause your thread to complete. In onCreate() you can check if you have a running thread, and if so, tell it to stop. Here's a code example:
In your activity:
private static Thread myThread;
In your activity, when you create the thread:
if (myThread != null) {
if (myThread.isAlive()) {
myThread.running = false; // Tell the thread to stop running now
}
}
myThread = new Thread(...);
myThread.start();
In your thread:
public boolean running = true; // Initator of this thread should set this to false to make the thread complete
public void run() {
while (running) {
// do whatever your thread does in a loop
}
}
You can stop the ruuning threads onDestroy() of activity.
please find the below eg:
static boolean stopThread=false;
public myThread implements Ruunable{
public void run(){
while(true){
//your logic
if(stopThread)
break;
}
}
#Override
protected void onDestroy()
{
stopThread=true;
}
When somebody is doing some game they can do it like this: mainActivity which extends Activity and in this main activity there is a method e.g:
setContentView(BouncingBallView);
BouncingBallView extends View and there we have got methods: onDraw() invalidate() and these methods are use to do update and they are performing in all frames.
My problem is I would like to have some method like "onDraw-invalidate" which are update but in class Activity not in View.
I would like to know if there are some main loop, methods which are perform all the time some update()? I know that in Activity there is: onCreate(); onStart(); onRestart(); onResume(); onPause(); onStop(); and onDestroy(), but I can't see update? How would I do this?
Do you want periodic updates? Then a timer might be a way to go. Create an instance of a timer in your activity's onStart and schedule an update task with a desired delay as follows:
public class MyActivity extends Activity {
...
private Timer timer;
private BouncingBallView ballView;
...
#Override
public void onResume() {
timer = new Timer();
// This timer task will be executed every 1 sec.
timer.schedule(new TimerTask() {
#Override
public void run() {
ballView.update();
}
}, 0, 1000);
}
...
#Override
public void onSuspend() {
// Suspend the updates when the activity is inactive.
timer.cancel();
}
}
Note that timer tasks run in a separate thread, and in Android modifying UI elements in a different thread from the one they were created in may cause problems. If you run into these problems handlers (android.os.Handler) are helpful, and in Honeycomb there are better solutions for that but the Timer/Handler combination works well in older versions.