简体   繁体   中英

runnable that started on a new thread does not stop when removeCallbacks() is called

I have the following below code.

//This is global for the activity.
Handler handler = new Handler()
{
    @Override
    public void handleMessage(Message msg)
    {   
               //update the UI
    }
};

In my onResume() I am starting a new thread that runs a runnable.

protected void onResume()
{
    super.onResume();

    Thread t = new Thread(runnable);
    t.start();
}

My runnable is as follows :

Runnable runnable = new Runnable()
{
    public void run()
    {
                  // some networking stuff 
                  // some db stuff
                  // whatever


        handler.sendEmptyMessage(0);
        handler.postDelayed(new Runnable()
        {
            public void run()
            {
                new Thread(runnable).start();
            }
        }, 30000);
    }
}

And I have this inside onPause() :

protected void onPause()
    {       
        super.onPause();
            handler.removeCallbacks(runnable);
    }

At the end I call the handler.sendEmptyMessage(0); so that the handleMessage(Message msg) gets called and I do the UI changes, and I repeat the task but starting a new runnable, which starts a new thread that runs the same runnable as this.

Clarification questions :

  1. I am starting a new Thread inside my onResume(), which means that the runnable is not running on the UI Thread, however, the handler is being created on the UI thread and is naturally attached to the UI thread. How is the UI is being changed flawlessly ?

  2. It is supposed for handler.removeCallbacks(runnable), however, whenever I minized the app, the runnable still keeps on running every 30 seconds. (this might be because it is on a new thread, that is not associated with the Handler created). How can I make it stop ?

public class MainActivity extends Activity {

    public static final int UPDATE = 1;
    public static final int WORK = 2;

    private Handler uiHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case UPDATE:
                // Perform UI updates here
                ....
                // UI Updates done, schedule WORK in 30 seconds:
                this.sendMessageDelayed(this.obtainMessage(WORK), 30000);
                break;
            case WORK:
                new Thread(doWork).start();
                break;

            default:
                super.handleMessage(msg);
            }
        }

    };

private WeakReference<Handler> handlerRef = new WeakReference<Handler>( uiHandler );

    private Runnable doWork = new Runnable() {

        @Override
        public void run() {
            // This will run on a different thread.

            // If UI is still around, tell it to update
            Handler ui = handlerRef.get();
            if( ui != null )
                ui.sendEmptyMessage(MainActivity.UPDATE);
        }
    };  

    @Override
    protected void onPause() {
        uiHandler.removeMessages(WORK);
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        // Resume UI updates in 500ms, allowing UI to settle
        uiHandler.sendMessageDelayed(uiHandler.obtainMessage(WORK), 500);
    }

    ....
}

This pattern uses a single Handler on the UI thread. Background work is done in the Runnable, which the ui Handler will post to a new Thread, so avoiding NetworkOnMainThreadException and -- more importantly -- unresponsive UI. Further, a new update is scheduled thirty seconds after the background process has completed, to avoid taxing the system with long-running updates. The background thread uses a WeakReference to the ui Handler, so if the Activity is killed while the thread is working, it won't send UI updates to it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM