2

我有以下代码。

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

在我的 onResume() 中,我正在启动一个运行可运行文件的新线程。

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

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

我的可运行文件如下:

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);
    }
}

我在 onPause() 里面有这个:

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

最后,我调用了,handler.sendEmptyMessage(0);以便handleMessage(Message msg)调用它并更改 UI,然后重复该任务,但启动一个新的可运行对象,这将启动一个运行与此相同的可运行对象的新线程。

澄清问题:

  1. 我在 onResume() 中启动了一个新线程,这意味着可运行对象没有在 UI 线程上运行,但是,处理程序是在 UI 线程上创建的,并且自然地附加到 UI 线程。UI是如何完美改变的?

  2. 它应该用于 handler.removeCallbacks(runnable),但是,每当我最小化应用程序时,runnable 仍然每 30 秒运行一次。(这可能是因为它在一个新线程上,与创建的处理程序无关)。我怎样才能让它停止?

4

1 回答 1

1
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);
    }

    ....
}

此模式在 UI 线程上使用单个 Handler。后台工作在 Runnable 中完成,ui 处理程序会将其发布到新线程,因此避免了NetworkOnMainThreadException——更重要的是——无响应的 UI。此外,在后台进程完成后 30 秒安排新的更新,以避免长时间运行的更新对系统造成负担。后台线程使用WeakReferenceui 处理程序,因此如果在Activity线程工作时被杀死,它不会向它发送 UI 更新。

于 2013-09-30T14:23:51.380 回答