1. 程式人生 > >Android開發學習之路--異步消息Handler,Message,Looper和AsyncTask之初體驗

Android開發學習之路--異步消息Handler,Message,Looper和AsyncTask之初體驗

被調用 project 輸入 gettext npos article app sso 音樂播放

在簡易音樂播放器中。用了Handler。也沒有過多地去研究學習,這裏再學習下android下的異步消息處理機制。

這裏用了Handler主要是在線程中不能更新UI,而須要通過Handler才幹夠。關於異步消息處理有幾個概念。

1、Message:消息,線程間通訊的數據單元。

比如後臺要下載歌曲然後下載完畢要更新ui,則能夠發送一條包括更新信息的Message給UI線程。

2、MessageQueue:消息隊列。用來存放全部通過Handler公布的消息,由於是隊列。所以是先進先出的。

3、Handler:Message的主要處理者。負責將Message加入到消息隊列以及對消息隊列中的Message進行處理。

4、Looper:循環管理MessageQueue。循環取出MessageQueue中的Message。並交給對應的Handler進行處理。

5、線程:UI thread是main thread,android啟動程序時會替他建立一個MessageQueue。

每個線程裏可含有一個Looper對象以及一個MessageQueue數據結構。

以下來個樣例吧還是,新建projectHandlerTest。編寫簡單布局例如以下:

<?

xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:layout_margin="10dp" tools:context="com.example.jared.handlertest.MainActivity"> <EditText android:id="@+id/inputContent" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="輸入要改變的內容"/> <Button android:id="@+id/changeViewContent" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Change The ViewContent" android:textAllCaps="false"/> <TextView android:id="@+id/testHandler" android:text="I am old!!!" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="20dp" android:textSize="22dip" android:layout_gravity="center"/> </LinearLayout>


這裏輸入內容。按button,改變TextView的內容。編寫MainActivity代碼例如以下:

package com.example.jared.handlertest;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    public static final int UPDATA_VIEW = 1;

    private TextView textView;
    private Button changeContent;
    private EditText inputContent;

    private Thread  mThread;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case UPDATA_VIEW:
                    String mInputContent = inputContent.getText().toString();
                    textView.setText(mInputContent);
                    break;
                default:
                    break;
            }
        }
    };

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

        textView = (TextView)findViewById(R.id.testHandler);
        inputContent = (EditText)findViewById(R.id.inputContent);

        changeContent = (Button)findViewById(R.id.changeViewContent);
        changeContent.setOnClickListener(new myOnClickListener());
    }

    private class myOnClickListener implements View.OnClickListener {
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.changeViewContent:
                    mThread = new Thread(runnable);
                    mThread.start();
                    break;
                default:
                    break;
            }
        }
    }

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            Message message = new Message();
            message.what = UPDATA_VIEW;
            mHandler.sendMessage(message);
        }
    };
}

這裏先new了一個Handler,handleMessage方法處理發送的Message。Thread裏面發送message,然後更新TextView的內容,執行例如以下:

技術分享 技術分享

主要的Handler已經完畢了,以下再學習下AsyncTask。

AsyncTask是方便編寫後臺線程和UI線程的輔助類。

它內部的實現是一個線程池。每一個後臺會提交到線程池中去運行。AsyncTask有三個模板函數:

1、Params:傳遞給後臺任務的參數類型。

2、Progress:後臺計算運行過程中,進步的單位類型。

3、Result:後臺運行返回的結果的類型。

當標示不須要的類型的時候,僅僅要用Void即可了。

AsyncTask須要重寫5個方法。各自是:

1、onPreExecute方法:準備執行。該回調函數在任務被執行之後馬上由UI線程調用。一般能夠顯示運行進度條。

2、doInBackground(Params ...)方法:正在後臺執行。通常在這裏執行耗時的後臺計算,計算結果返回給函數,這裏假設AsyncTask的第三個參數是Void的話不須要返回,這裏不能更新UI。可是能夠調用publishProgress(Progress ...)方法完畢。

3、onProgressUpdate(Progress ...)方法:進度更新,UI線程在publishProgress(Progress ...)方法調用完畢後被調用。一般動態顯示一個進度。

4、onPostExecute(Result)方法:完畢後臺任務,會返回,這裏能夠進行些UI的操作,比方提醒任務運行的結果。以及關閉掉進度條對話框等。

5、onCancelled方法:取消任務,在調用AsyncTask的cancel()方法的時候調用。

以下通過AsyncTask的方式來進行上面的樣例。Handler的代碼就沒有刪除掉了,代碼例如以下:

package com.example.jared.handlertest;

import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    public static final int UPDATA_VIEW = 1;

    private TextView textView;
    private Button changeContent;
    private EditText inputContent;

    private Thread  mThread;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case UPDATA_VIEW:
                    String mInputContent = inputContent.getText().toString();
                    textView.setText(mInputContent);
                    break;
                default:
                    break;
            }
        }
    };

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

        textView = (TextView)findViewById(R.id.testHandler);
        inputContent = (EditText)findViewById(R.id.inputContent);

        changeContent = (Button)findViewById(R.id.changeViewContent);
        changeContent.setOnClickListener(new myOnClickListener());
    }

    private class myOnClickListener implements View.OnClickListener {
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.changeViewContent:
                   // mThread = new Thread(runnable);
                   // mThread.start();
                    changeViewContentTask  task = new changeViewContentTask();
                    task.execute();
                    break;
                default:
                    break;
            }
        }
    }

    class changeViewContentTask extends AsyncTask<Void, Integer, Boolean> {
        @Override
        protected Boolean doInBackground(Void... voids) {
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
        }

        @Override
        protected void onPostExecute(Boolean b) {
            String mInputContent = inputContent.getText().toString();
            textView.setText(mInputContent);
        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected void onCancelled() {
        }
    }

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            Message message = new Message();
            message.what = UPDATA_VIEW;
            mHandler.sendMessage(message);
        }
    };
}
這裏實例化一個task。然後task.execute();就能夠運行了,效果如上就不添圖了。

Android開發學習之路--異步消息Handler,Message,Looper和AsyncTask之初體驗