Android中的異步操作(多線程)

在Android中實現異步任務機制有兩種方式,Handler和AsyncTask。

一、Handler:

主要接受子線程發送的數據, 並用此數據配合主線程更新UI。由於Handler運行在主線程中(UI線程中), 它與子線程可以通過Message對象來傳遞數據, 這個時候,Handler就承擔着接受子線程傳過來的(子線程用sedMessage()方法傳弟)Message對象,(裏面包含數據) , 把這些消息放入主線程隊列中,配合主線程進行更新UI。
1.Handler中的方法:
handler可以分發Message對象和Runnable對象到主線程中, 每個Handler實例,都會綁定到創建他的線程中(一般是位於主線程),
它有兩個作用: (1): 安排消息或Runnable 在某個主線程中某個地方執行, (2)安排一個動作在不同的線程中執行
Handler中分發消息的一些方法
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
以上post類方法允許你排列一個Runnable對象到主線程隊列中,
sendMessage類方法, 允許你安排一個帶數據的Message對象到隊列中,等待更新.
2.Handler實例:
public class MyHandlerActivity extends Activity {
    Button button;
    MyHandler myHandler;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.handlertest);

        button = (Button) findViewById(R.id.button);
        myHandler = new MyHandler();
        // 當創建一個新的Handler實例時, 它會綁定到當前線程和消息的隊列中,開始分發數據
        // Handler有兩個作用, (1) : 定時執行Message和Runnalbe 對象
        // (2): 讓一個動作,在不同的線程中執行.

        // 它安排消息,用以下方法
        // post(Runnable)
        // postAtTime(Runnable,long)
        // postDelayed(Runnable,long)
        // sendEmptyMessage(int)
        // sendMessage(Message);
        // sendMessageAtTime(Message,long)
        // sendMessageDelayed(Message,long)
       
        // 以上方法以 post開頭的允許你處理Runnable對象
        //sendMessage()允許你處理Message對象(Message裏可以包含數據,)

        MyThread m = new MyThread();
        new Thread(m).start();
    }

    /**
     * 接受消息,處理消息 ,此Handler會與當前主線程一塊運行
     * */

    class MyHandler extends Handler {
        public MyHandler() {
        }

        public MyHandler(Looper L) {
            super(L);
        }

        // 子類必須重寫此方法,接受數據
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            Log.d("MyHandler", "handleMessage......");
            super.handleMessage(msg);
            // 此處可以更新UI
            Bundle b = msg.getData();
            String color = b.getString("color");
            MyHandlerActivity.this.button.append(color);

        }
    }

    class MyThread implements Runnable {
        public void run() {

            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            Log.d("thread.......", "mThread........");
            Message msg = new Message();
            Bundle b = new Bundle();// 存放數據
            b.putString("color", "我的");
            msg.setData(b);

            MyHandlerActivity.this.myHandler.sendMessage(msg); // 向Handler發送消息,更新UI

        }
    }

}

二、AsyncTask

AsyncTask是抽象類.AsyncTask定義了三種泛型類型 Params,Progress和Result。
  Params 啓動任務執行的輸入參數,比如HTTP請求的URL。
  Progress 後臺任務執行的百分比。
  Result 後臺執行任務最終返回的結果,比如String。

AsyncTask的執行分爲四個步驟,每一步都對應一個回調方法,這些方法不應該由應用程序調用,開發者需要做的就是實現這些方法。
  1) 子類化AsyncTask
  2) 實現AsyncTask中定義的下面一個或幾個方法
   onPreExecute(), 該方法將在執行實際的後臺操作前被UI thread調用。可以在該方法中做一些準備工作,如在界面上顯示一個進度條。
   doInBackground(Params...), 將在onPreExecute 方法執行後馬上執行,該方法運行在後臺線程中。這裏將主要負責執行那些很耗時的後臺計算工作。可以調用 publishProgress方法來更新實時的任務進度。該方法是抽象方法,子類必須實現。
   onProgressUpdate(Progress...),在publishProgress方法被調用後,UI thread將調用這個方法從而在界面上展示任務的進展情況,例如通過一個進度條進行展示。
   onPostExecute(Result), 在doInBackground 執行完成後,onPostExecute 方法將被UI thread調用,後臺的計算結果將通過該方法傳遞到UI thread.

爲了正確的使用AsyncTask類,以下是幾條必須遵守的準則:
  1) Task的實例必須在UI thread中創建
  2) execute方法必須在UI thread中調用
  3) 不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法
  4) 該task只能被執行一次,否則多次調用時將會出現異常
doInBackground方法和onPostExecute的參數必須對應,這兩個參數在AsyncTask聲明的泛型參數列表中指定,第一個爲doInBackground接受的參數,第二個爲顯示進度的參數,第第三個爲doInBackground返回和onPostExecute傳入的參數。
AsyncTask實例:
package test.list;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class NetworkActivity extends Activity{
    private TextView message;
    private Button open;
    private EditText url;

    @Override
    public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.network);
       message= (TextView) findViewById(R.id.message);
       url= (EditText) findViewById(R.id.url);
       open= (Button) findViewById(R.id.open);
       open.setOnClickListener(new View.OnClickListener() {
           public void onClick(View arg0) {
              connect();
           }
       });

    }

    private void connect() {
        PageTask task = new PageTask(this);
        task.execute(url.getText().toString());
    }


    class PageTask extends AsyncTask<String, Integer, String> {
        // 可變長的輸入參數,與AsyncTask.exucute()對應
        ProgressDialog pdialog;
        public PageTask(Context context){
            pdialog = new ProgressDialog(context, 0);   
            pdialog.setButton("cancel", new DialogInterface.OnClickListener() {
             public void onClick(DialogInterface dialog, int i) {
              dialog.cancel();
             }
            });
            pdialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
             public void onCancel(DialogInterface dialog) {
              finish();
             }
            });
            pdialog.setCancelable(true);
            pdialog.setMax(100);
            pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            pdialog.show();


        }
        @Override
        protected String doInBackground(String... params) {

            try{

               HttpClient client = new DefaultHttpClient();
               // params[0]代表連接的url
               HttpGet get = new HttpGet(params[0]);
               HttpResponse response = client.execute(get);
               HttpEntity entity = response.getEntity();
               long length = entity.getContentLength();
               InputStream is = entity.getContent();
               String s = null;
               if(is != null) {
                   ByteArrayOutputStream baos = new ByteArrayOutputStream();

                   byte[] buf = new byte[128];

                   int ch = -1;

                   int count = 0;

                   while((ch = is.read(buf)) != -1) {

                      baos.write(buf, 0, ch);

                      count += ch;

                      if(length > 0) {
                          // 如果知道響應的長度,調用publishProgress()更新進度
                          publishProgress((int) ((count / (float) length) * 100));
                      }

                      // 讓線程休眠100ms
                      Thread.sleep(100);
                   }
                   s = new String(baos.toByteArray());              }
               // 返回結果
               return s;
            } catch(Exception e) {
               e.printStackTrace();

            }

            return null;

        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
        }

        @Override
        protected void onPostExecute(String result) {
            // 返回HTML頁面的內容
            message.setText(result);
            pdialog.dismiss(); 
        }

        @Override
        protected void onPreExecute() {
            // 任務啓動,可以在這裏顯示一個對話框,這裏簡單處理
            message.setText(R.string.task_started);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            // 更新進度
              System.out.println(""+values[0]);
              message.setText(""+values[0]);
              pdialog.setProgress(values[0]);
        }

     }

}
參考:http://www.pin5i.com/showtopic-android-handler.html
            http://blog.csdn.net/liuhe688/article/details/6532519這篇文章講的AsyncTask很詳細。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章