2

For example, if we consider the snippet code below:

public class HandlerExample extends AppCompatActivity {

    private Handler mLeakyHandler = new Handler();
    private TextView myTextBox;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_samples);
        myTextBox = (TextView) findViewById(R.id.tv_handler);

        // Post a message and delay its execution for 10 seconds.
        mLeakyHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                myTextBox.setText("Done");
            }
        }, 1000 * 10);
    }
}

When the Activity gets destroyed, whether by a configuration change or another reason, the Runnable will not. The same goes for Asynctasks.

My question is, what makes it not being destroyed even if it's declared in that Activity?

Consider that I am asking about the why.

Onik
  • 19,396
  • 14
  • 68
  • 91
HiddenDroid
  • 1,440
  • 4
  • 14
  • 27
  • if you dont mess with threads and activity lifecycle, loaders are best options for u. https://developer.android.com/guide/components/loaders.html – ugur Sep 19 '16 at 00:00
  • its different because they are not an Activity. – petey Sep 20 '16 at 18:25

2 Answers2

3

Because Activity class runs on UI Thread and Runnable, AsyncTask etc run on Background Threads that are separate from the ui thread. And ending the Activity won't end other threads unless you specifically instruct it to do so.

Runnable Description:

The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread.

AsyncTask Description:

AsyncTask enables proper and easy use of the UI thread. This class allows you to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

and also you can learn more about Threads by reading the documentation.

Iulian
  • 1,156
  • 11
  • 19
  • The handler doesn't run on backgrounds threads all the times. It runs on the thread from which it was created. For the snippet code above, it runs on the UI thread since it was created on the UI thread. – HiddenDroid Sep 19 '16 at 22:31
  • The handler runs on the thread it is created on, handler is just an helper object to send and receive from the message queue. Destroying the activity will also destroy the handler but it won't destroy the runnable which runs on a different thread. https://developer.android.com/reference/android/os/Handler.html – Iulian Sep 19 '16 at 22:48
  • on the UI Thread then i call `Runnable.run()` where will this run? i think you should clarify that in your answer though, and also i think the implementation of runnables and other interfaces have evolved from just puttin them in threads – Elltz Sep 19 '16 at 22:56
  • @Super-califragilistic _"on the UI Thread then i call Runnable.run() where will this run?"_ On the UI thread. – Onik Sep 19 '16 at 23:14
1

What makes it not being destroyed even if it's declared in that Activity?

When new Handler() is called on a thread (the main thread in your case), the Handler is associated with the Looper's message queue of the thread, sending to and processing Runnables and messages from the queue. Those Runnables and messages have a reference to the target Handler. Even though Activity's onDestroy() method isn't a "destructor", i.e. when the method returns the Activity's instance won't be immediately killed (see), the memory cannot be GC-ed because of an implicit reference to the Activity as being an outer class of the Runnable. The Activity won't be GC-ed for the delay time, i.e. until the Runnable be de-queued from the Looper's message queue and processed.

References:

  1. This Handler class should be static or leaks might occur: IncomingHandler
  2. How to Leak a Context: Handlers & Inner Classes
Community
  • 1
  • 1
Onik
  • 19,396
  • 14
  • 68
  • 91