Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android:異步任務基礎

Android:異步任務基礎

編輯:關於Android編程

今天面試的時候,面試官和我說起同步和異步,因為說起同步我就是想到線程同步,然後共享臨界資源啊死鎖啊什麼的,所以一直在說這個,線程異步倒是從來沒聽過。剛才看了場球想起這件事查了一下,不知道他說的異步是不是期待我回答用Handler來刷新主線程的意思,我平常管這個叫異步任務- -昨天一面的時候,面試官問的就是怎樣刷新UI線程,然後我就說用AsyncTask。好了,既然如此不管了,因為之前就想把以前寫的那篇AsyncTask重寫了。也算是讓焦急的等待時間過快點吧。


異步任務相關

Android從2.3(還是3.0…?)開始就不允許在主線程裡面執行一些比較耗時的任務,通常我們需要用一個異步任務的機制解決在子線程裡面刷新UI的問題。

簡單翻譯一下API上幾個重要的類:(我應該問面試官有沒相關的類可以提醒一下的)

Message:定義一個可以攜帶一些字段或對象數據的消息對象,官方推薦實例化方式是:Message.obtain() MessageQueue:存放消息的隊列 Handler:當你創建一個新的Handler時,他就和當前線程創建的MessageQueue綁定了。主要有兩個作用,一個是將消息入隊,另外一個是處理消息。 Looper:運行線程message queue的一個類,線程默認是不帶message queue的,可以通過prepare()loop()來創建。而主線程是自帶message queue的。

盜流程示意圖一張:
這裡寫圖片描述


實現異步任務的三種方式

目前我所知道的實現異步任務的方法有三個:

使用Handler + Message來實現 使用AsyncTask類 調用runOnUiThread()方法

下面以代碼注釋形式來講解一下三種方法的使用:

Handler+Message

public class MainActivity extends ActionBarActivity {
    private TextView textView;

    // 匿名內部類實例化一個Handler對象
    private Handler handler = new Handler() {
        // 重寫handleMessage方法,通過異步消息機制實現子線程刷新UI
        public void handleMessage(Message msg) {
            textView.setText("you got " + msg.what + " through handler");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textview);
        new TestThread().start();
    }

    private class TestThread extends Thread {
        private int i = 1;

        public void run() {
            while (true) {
                /* 這裡需要注意一下,我們可以Message message = Message.obtain()獲得Message對象,然後用Handler調用sendMessage()方法,更多詳細的方法可以參考API*/
                handler.sendEmptyMessage(i++);
                if (i > 100)
                    break;
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

AsyncTask

這裡直接把之前那篇文章的代碼貼過來,因為後面應該會刪掉那篇文章。

public class MainActivity extends ActionBarActivity {  

    Private TextView textView;  
    Private Button button;  
    Private MyAsyncTask asyncTask;  

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

        textView = (TextView) findViewById(R.id.textview);  
        button = (Button) findViewById(R.id.button);  
        asyncTask = new MyAsyncTask();  

        // 點擊button進行異步任務
        button.setOnClickListener(new OnClickListener() {  

            @Override  
            public void onClick(View arg0) {  
                // TODO Auto-generated method stub  
                asyncTask.execute("Leelit"); // 這個參數就是傳入參數,常用於URL網絡下載,可以為空。  
            }  
        });  

    }  

    /* 泛型類AsyncTask有三個參數:Params,傳入參數;Progress,進度;Result,返回結果。也可以使用Void表示該參數為空。*/ 
    private class MyAsyncTask extends AsyncTask {  

        @Override  
        protected String doInBackground(String... string) {  
            // TODO Auto-generated method stub  
            String conutString = string[0]; // 字符串可變參數
            int z = 0;  
            // 進行5億次計算,模擬一個耗時任務  
            for (int i = 0; i < 1000000; i++) {   
                for (int j = 0; j < 500; j++) {  
                    z++;  
                }  
            }  
            conutString += " has executed ++ computation for " + z + " times";                                                         
            Log.e("ProcessInfo", "the task is done");   
            return conutString; // 將計算結果返回,傳給onPostExecute()  
        }  

        @Override  
        protected void onPostExecute(String result) {  
            // TODO Auto-generated method stub  
            super.onPostExecute(result);   
            textView.setText(result); // 刷新UI  
        }  
    }  

}  

如果需要顯示任務進度的話,可以重寫另外一個方法:

// 可變參數的類型就是泛型的第二個參數,因為我這裡不需要所以就是Void
@Override
protected void onProgressUpdate(Void... values) {
    // TODO Auto-generated method stub
    super.onProgressUpdate(values);
}

並在doInBackground()方法調用publishProgress()
 


runOnUiThread()

直接在子線程裡面調用這個方法就可以實現對主線程的操作,是最簡單的操作

public class MainActivity extends ActionBarActivity {

    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textview);
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                final String result = "After a long-time execution";
                // 直接在子線程調用即可
                runOnUiThread(new Runnable() {
                    public void run() {
                        textView.setText(result);
                    }
                });
            }
        }).start();
    }

}

看一下這個這麼簡單的方法的源碼

public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }

沒錯,可以看到就是通過封裝Handler來實現的,其實AsyncTask也是如此,不過AsyncTask的機制復雜一點。


小結:異步任務可用Handler及其封裝的類或方法來實現

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved