1. 程式人生 > >Android多執行緒理解

Android多執行緒理解

Android 理解多執行緒

安卓應用程式通常是應用在一個單獨的執行緒裡的,即為主執行緒,用於顯示使用者介面以及響應使用者的操作。
如果一些耗時任務也同時在主執行緒裡去完成,則會影響使用者體驗,會阻塞UI主執行緒。我們會建立一個單獨的執行緒或者子執行緒,去處理這些耗時操作(如網路請求、資料庫操作等)。
那麼這些子執行緒就是AsyncTask、Thread、HandlerThread,它們叫做安卓的工作者執行緒。
- AsyncTask
- Handler


一、AsyncTask非同步任務

AsyncTask是Android的一個輕量級非同步類,可以自定義類並繼承AsyncTask,實現非同步任務處理操作。並且AsyncTask提供了介面返回非同步操作的進度,最後會返回結果到UI主執行緒中。

優點:簡單快捷,過程可以控制
缺點:在處理多個非同步操作時比較複雜

AsyncTask類

引數 說明
Params 啟動任務時輸入的執行引數,一般為一個網路地址
Progress 非同步任務執行的進度
Result 非同步任務執行後的結果的型別

程式碼例項

這是一個利用AsyncTask載入網路圖片的程式碼:

public class MainActivity extends ActionBarActivity
{
private Button button1;
private ImageView imageview1;
private ProgressDialog dialog;

private String image_uri =”https://imgsa.baidu.com/baike/c0%3Dbaike272%2C5%2C5%2C272%2C90/sign=c4f298bb97ef76c6c4dff379fc7f969f/9358d109b3de9c82f077b3156b81800a19d8431d.jpg”;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dialog = new ProgressDialog(this);
dialog.setTitle(“圖片下載”);
dialog.setMessage(“正在下載,請稍後…”);
button1 = (Button) findViewById(R.id.button1);
imageview1 = (ImageView) findViewById(R.id.imageView1);
button1.setOnClickListener(new OnClickListener()
{

        @Override
        public void onClick(View v)
        {
            // TODO Auto-generated method stub
            new DownloadTask().execute(image_uri);
        }
    });
}

//自定義下載類繼承AsyncTask
public class DownloadTask extends AsyncTask<String, Void, Bitmap>
{
    // 這個方法會在後臺任務開始執行之間呼叫,用於進行一些介面上的初始化操作,比如顯示一個進度條對話方塊等。
    @Override
    protected void onPreExecute()
    {
        // TODO Auto-generated method stub
        dialog.show();
        super.onPreExecute();
    }

    // 這個方法中的所有程式碼都會在子執行緒中執行,主要完成耗時任務
    // 注意,在這個方法中是不可以進行UI操作的
    //在執行過程中可以呼叫publishProgress(Progress... values)來更新進度資訊。
    @Override
    protected Bitmap doInBackground(String... params)
    {
        // TODO Auto-generated method stub
        // 使用網路連結類HttpClient完成網路資料的獲取
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(params[0]);
        Bitmap bitmap = null;
        try
        {
            HttpResponse httpResponse = httpClient.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() == 200)
            {
                HttpEntity httpEntity = httpResponse.getEntity();
                byte[] data = EntityUtils.toByteArray(httpEntity);
                bitmap = BitmapFactory
                        .decodeByteArray(data, 0, data.length);
            }
        } catch (Exception e)
        {
            // TODO: handle exception
            e.printStackTrace();
        }

        return bitmap;
    }
    //在呼叫publishProgress(Progress... values)時,此方法被執行,直接將進度資訊更新到UI元件上。
    @Override
    protected void onProgressUpdate(Void... values)
    {
        // TODO Auto-generated method stub
        super.onProgressUpdate(values);
    }

    // 可以利用返回的資料來進行一些UI操作,比如說提醒任務執行的結果,以及關閉掉進度條對話方塊等。
    protected void onPostExecute(Bitmap result)
    {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        imageview1.setImageBitmap(result);
        dialog.dismiss();
    }
}

}

參考:android AsyncTask介紹
詳解Android中AsyncTask的使用

二、Handler

1、Handler概念:

I 、Handler 是 Android 給我們提供來更新 UI 的一套機制,也是一套訊息處理的機制,我們可以傳送訊息,也可以通過它來處理訊息。
II、Android 在設計的時候,就封裝了一套訊息建立、傳遞、處理機制,如果不遵循這樣的機制就沒有辦法更新 UI 資訊,就會丟擲異常資訊。

2、與Handler相關的幾個概念:

I、Message 訊息,理解為執行緒間通訊的資料單元。例如後臺執行緒在處理資料完畢後需要更新UI,則可傳送一條包含更新資訊的Message給UI執行緒。
II、Message Queue 訊息佇列,用來存放通過Handler釋出的訊息,按照先進先出執行。
III、Handler Handler是Message的主要處理者,負責將Message新增到訊息佇列以及對訊息佇列中的Message進行處理。
Looper 迴圈器,扮演Message Queue和Handler之間橋樑的角色,迴圈取出Message Queue裡面的Message,並交付給相應的Handler進行處理。
IV、執行緒 UI thread 通常就是main thread,而Android啟動程式時會替它建立一個Message Queue。每一個執行緒裡可含有一個Looper物件以及一個MessageQueue資料結構。在你的應用程式裡,可以定義Handler的子類別來接收Looper所送出的訊息。

3、Handler的一些分發訊息的方法

    post(Runnable)
    postAtTime(Runnable,long)
    postDelayed(Runnable long)
    sendEmptyMessage(int)
    sendMessage(Message)
    sendMessageAtTime(Message,long)
    sendMessageDelayed(Message,long)

4、關於Message

建立Handler例項,要過載handleMessage方法,來處理訊息
獲取Message物件的最好方法是呼叫Message.obtain()

Message可傳遞的引數:

①. arg1 arg2 整數型別,是setData的低成本替代品,傳遞簡單型別。
Object 型別 obj
②. what 使用者自定義的訊息程式碼,這樣接受者可以瞭解這個訊息的資訊。每個handler各自包含自己的訊息程式碼,所以不用擔心自定義的訊息跟其他handlers有衝突
③.其他的可以通過Bundle進行傳遞
Message可以通過new Message構造來建立一個新的Message,但是這種方式很不好,不建議使用。最好使用Message.obtain()來獲取Message例項,它建立了訊息池來處理的。

5、程式碼例項
利用Handler建立一個dialog進度條並顯示進度

public class HandlerActivity extends Activity
{
private Button button1;
private static ProgressDialog dialog;
//建立Handler靜態物件
private static Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
int index=msg.arg1;
dialog.setProgress(index);
if (msg.what==1)
{
dialog.dismiss();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
button1=(Button)findViewById(R.id.button1);
dialog=new ProgressDialog(this);
dialog.setTitle(“正在下載…”);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
button1.setOnClickListener(new OnClickListener()
{

        @Override
        public void onClick(View v)
        {
            // TODO Auto-generated method stub
            new Thread(new MyThread()).start();
            dialog.show();
        }
    });
}
//建立一個子執行緒繼承Runnable
public class MyThread implements Runnable{
    int count=1;
    int index=0;
    @Override
    public void run()
    {
        // TODO Auto-generated method stub
        while(count<=100){
            try
            {
                Thread.sleep(200);
            } catch (Exception e)
            {
                // TODO: handle exception
                e.printStackTrace();
            }
            Message message=Message.obtain();
            message.arg1=count;
            handler.sendMessage(message);
            count++;
        }
        Message end=Message.obtain();
        end.what=1;
        handler.sendMessage(end);
    }
}

參考:Android中的Handler的機制與用法詳解
Android中的Handler總結