Performing long running operation in onDestroy
Asked Answered
A

2

7

I have a "long-running" cleanup operation that I need to perform in onDestroy() of my Activity. What is the best way to do this?

If I use a Thread to do this, my onDestroy() will return immediately; but what happens to the Thread reference? I am looking for advice on any implications/gotchas/trip-wires that I need to be aware of here since I assume that the process will still be alive even after the Activity is destroyed.


Background:

I am using JmDNS in my app. When the user is done with my app, I want to clean up the JmDNS instance. I do this using the close() method of JmDNS class. However, this method takes more than 5 seconds to complete. As a result, the user sees my Activity on screen for a long time after touching the Back key.

I am yet to figure out why the close() takes that long, but in the meanwhile I also realized that I really don't need to wait for the close to complete successfully. All I need is a way to "trigger" the close and be done with it.

Aerophagia answered 28/2, 2012 at 9:23 Comment(2)
Jmdns is usually used for discovering network service, I don't know the reason why you need keep it open and running until application finally closed. I usually close it immediately once I found the remote server and done with it, and prompt user a ProgressDialog in the mean time.Ringsmuth
Yes- that is my normal use case. I have another use case where I need to continuously monitor for service being discovered/dropped and take action accordingly, throughout the life time of the app.Aerophagia
A
3

I ended up doing what I had asked in the question - I start a Thread to perform the long-running operation in onDestroy().

One case I had to consider was when the user re-opens my app even before the long-running has completed. In my app, this means a new instance of JmDNS gets created. So, I clean up each instance separately in my onDestroy.

Your use case might differ - you might want launch the cleanup thread only if it is not already running (using Thread's isAlive() method or some such technique).

Here's some sample code. To appreciate the "clean up each instance separately" part, perform the following sequence of steps:

  1. Launch the app
  2. Press the back button. You will see the clean up operation in LogCat
  3. Re-launch the app.
  4. Again, exit the app. Now, you will see two sets of cleanup logs - the first one representing cleanup for the first instance; and the second set corresponding to the second instance.

    public class DelayedExitActivity extends Activity {
    
        private static final String LOG_TAG = "DelayedExit";
        private final  Runnable longOperation = new Runnable(){
            @Override
            public void run() {
                for (int i=0 ; i < 50; i++){
                    Log.d(LOG_TAG, "Iteration "+i);
                    try {
                        Thread.sleep(2 * 1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        };
        private Thread longThread ;
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
        }
    
        @Override
        protected void onDestroy() {
            if(longThread == null){
                longThread = new Thread(longOperation);
            }
            longThread.start();
            super.onDestroy();
        }
    }
    
Aerophagia answered 5/3, 2012 at 9:19 Comment(1)
Just a heads up to those reading this solution. It will work but note that this will keep an implicit reference to the activity and you will have a memory leak for as long as this operation is active.Fiore
S
0

Try to start your thread in onBackPressed() and call destroy() when your thread will be finished.

Seagrave answered 28/2, 2012 at 9:28 Comment(5)
Don't you mean I should call finish() once the thread finishes? In this case, what is the user expected to see upon pressing Back key?Aerophagia
Yes, i mean You should call finish(). Yuo can show ProgressDialog or anything else upon pressing back key.Seagrave
I'm reluctant to make the user wait for my app to close! Since I'm not interested in the result of the cleanup operation, I was wondering if I can start the cleanup in a thread and simply continue with the Activity destruction. That way, the user immediately "exits" the app while the cleanup happens in the background. My only concern is what will happen to that background thread; and what will happen if user re-launches my app before that background thread has completed.Aerophagia
Nothing will happen if your application willn't use the same things that thread useSeagrave
That won't handle switching to another activity and destroying later from stopped state.Steamer

© 2022 - 2024 — McMap. All rights reserved.