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);UIhandleMessage(Message msg)を変更します。タスクを繰り返しますが、新しいランナブルを開始すると、これと同じランナブルを実行する新しいスレッドが開始されます。

明確化のための質問:

  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 Handler に を使用するため、Activityスレッドの動作中に が強制終了された場合、UI の更新は送信されません。

于 2013-09-30T14:23:51.380 に答える