Android 執行緒 - Thread 與 Handler

相信許多耗時的工作是需要再背景執行,此篇來介紹執行緒的用法,我們舉個數到十的例子。其實 Thread 的使用相當簡單,不囉嗦,請看 Code:

public class MainActivity extends Activity
{

    Thread countToTen;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        countToTen = new CountToTen();
        countToTen.start();
    }

    class CountToTen extends Thread
    {

        @Override
        public void run()
        {
            // TODO Auto-generated method stub
            super.run();

            try {
                for (int i = 0; i < 10; i++) {
                    Thread.sleep(1000);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

我個人建議宣告一個 Thread 變數比較好管理,當然如果你保證這個 Thread 可以很快跑完就結束,或是它並非很重要的任務,不需要特別管理的話,也可以使用以下寫法:

public class MainActivity extends Activity
{

    Thread countToTen;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Thread(new Runnable() {

            public void run() {
                // TODO Auto-generated method stub
                // 您要在執行緒作的事
            }
        }).start();
    }
}

重點來了 Thread 裡是無法做任何有關介面的事,所以我們必須倚賴 Handler,可以把它想成介面與執行緒之間的經紀人。那程式該如何寫?假設我們想每數一秒就秀個訊息告訴使用者,那請參考以下寫法:

public class MainActivity extends Activity
{
    Thread countToTen;
    TextView txtCount;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        txtCount = (TextView) findViewById(R.id.txtCount);

        countToTen = new CountToTen();
        countToTen.start();
    }

    private Handler mHandler = new Handler()
    {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            txtCount.setText(Integer.toString(msg.getData().getInt("count", 0)));
        }
    };

    class CountToTen extends Thread
    {

        @Override
        public void run()
        {
            // TODO Auto-generated method stub
            super.run();

            try {
                for (int i = 0; i < 10; i++) {
                    Thread.sleep(1000);
                    Bundle countBundle = new Bundle();
                    countBundle.putInt("count", i + 1);

                    Message msg = new Message();
                    msg.setData(countBundle);

                    mHandler.sendMessage(msg);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

我們利用 Message 類別,將想傳送的資料藉由 Bundle 夾帶在 Message 中傳送給 Handler,讓 Handler 可以在接受到資訊後更新介面,我們可以想像 Massage 就是郵件,而 Bundle 就是附加檔,所以其程式函意為傳送有附加檔的郵件給經紀人,讓它通知介面該做甚麼事!

接下來做個簡單的管理執行緒,因為 Thread 不會跟著 Activity 結束就結束,它可以背景執行,所以我們希望在 Activity 結束時中斷它,我們可以加在 onPause() 中。

@Override
protected void onPause()
{
    // TODO Auto-generated method stub
    super.onPause();

    if (countToTen != null) {
        if (!countToTen.isInterrupted()) {
            countToTen.interrupt();
        }
    }
}

Ref : http://andcooker.blogspot.tw/2012/09/android-thread-handler.html