Android線程間通信之Handler

分類:技術 時間:2016-10-25

Handler機制及基本使用也已經是老生常談了~~~

1、概述

Android中拒絕子線程中更新UI。且主線程中過多執行耗時操作會造成界面卡頓導致ANR影響用戶體驗,因此Handler線程間通信的信使應運而生。Handler有兩個主要用途:(1)調度消息和runnable對象作為將來的執行;及(2)將被執行在一個不同的線程自己的方法。

1.Handler基本原理

主線程(UI線程)

子線程(work線程)

Message 消息類

MessageQueue消息隊列(數據結構中的隊列,先進先出規則)

Handler對象發送消息對象到消息隊列中,Looper循環取出消息隊列中的消息對象,并將該消息對象設置為發送該消息對象的handler的handleMessage方法的參數,若消息隊列中沒有消息則處于阻塞狀態。

2、Handler的基本使用

1.UI線程中發送消息并在UI線程中執行

Handler發送和處理消息的幾個方法:

void  handleMessage(Message  msg):處理消息的方法,該方法通常被重寫。
   final boolean hasMessage(int  what):檢查消息隊列中是否包含有what屬性為指定值的消息
   final boolean hasMessage(int what ,Object object):檢查消息隊列中是否包含有what好object屬性指定值的消息
   sendEmptyMessage(int what):發送空消息
   final Boolean send EmptyMessageDelayed(int what ,long delayMillis):指定多少毫秒發送空消息
   final  boolean sendMessage(Message msg):立即發送消息
   final boolean sendMessageDelayed(Message msg,long delayMillis):多少秒之后發送消息

由于代碼比較簡單,直接上代碼了~

/**
 * Created by magic on 2016年10月23日.主線程中發送消息主線程中接收
 */
@SuppressLint(quot;HandlerLeakquot;)
public class MainActivity extends Activity {

    TextView textView;
    Button button;
    Handler handler = new Handler() {
        // 接收消息并處理
        public void handleMessage(Message msg) {
            System.out.println(Thread.currentThread().getName());
            // main
            System.out.println(quot;消息-gt;quot;   msg.arg1   quot;-quot;   msg.obj);
            // 消息-gt;1-obj消息
        };
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        button = (Button) findViewById(R.id.btn);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // 主線程中發送消息
                Message message = handler.obtainMessage();
                message.arg1 = 1;
                message.obj = quot;obj消息quot;;
                handler.sendMessage(message);
                // 輸出當前線程名稱
                System.out.println(Thread.currentThread().getName());
                // main
            }
        });
    }

}

2.Work線程中發送消息并在UI線程中執行

/**
 * Created by magic on 2016年10月23日.Work線程中發送消息 UI線程中接收消息
 */
@SuppressLint(quot;HandlerLeakquot;)
public class TwoActivity extends Activity {

    Button button;
    Handler handler = new Handler() {
        // 接收消息并處理
        public void handleMessage(Message msg) {
            System.out.println(Thread.currentThread().getName());
            // main
            System.out.println(quot;消息-gt;quot;   msg.arg1   quot;-quot;   msg.obj);
            // 消息-gt;1-obj消息
        };
    };

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

        button = (Button) findViewById(R.id.btn);
        button.setText(quot;Work-gt;UIquot;);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                Thread thread = new Thread(new Runnable() {

                    @Override
                    public void run() {
                        // work線程中發送消息
                        Message message = handler.obtainMessage();
                        message.arg1 = 1;
                        message.obj = quot; obj消息quot;;
                        System.out.println(Thread.currentThread().getName());
                        // Thread-400
                        handler.sendMessage(message);
                        // 輸出當前線程名稱
                    }
                });
                // 開啟線程
                thread.start();
            }
        });
    }
}

3.UI線程中發送消息并在Work線程執行

基本步驟:

1.準備Looper對象

2.生成handler對象

3.Looper.loop()循環取出Message對象

/**
 * Created by magic on 2016年10月23日.UI線程中發送消息 work線程中接收消息
 */
@SuppressLint(quot;HandlerLeakquot;)
public class ThreeActivity extends Activity {

    Button button;
    Handler handler;

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

        textView = (TextView) findViewById(R.id.tev);
        button = (Button) findViewById(R.id.btn);
        button.setText(quot;UI-gt;Workquot;);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                Message message = handler.obtainMessage();
                message.arg1 = 1;
                message.obj = quot; obj消息quot;;
                // 主線程中發送消息
                handler.sendMessage(message);
                System.out.println(Thread.currentThread().getName());
                // main
            }
        });

        new MyThread().start();
    }

    class MyThread extends Thread {
        @Override
        public void run() {
            // 準備Looper對象
            Looper.prepare();
            handler = new Handler() {
                public void handleMessage(Message msg) {
                    System.out.println(Thread.currentThread().getName());
                    // Thread-401
                    System.out.println(quot;消息-gt;quot;   msg.what   quot;-quot;   msg.obj);
                    // 消息-gt;0- obj消息
                };
            };
            // 循環取出消息隊列中的消息對象
            Looper.loop();
            super.run();
        }
    }

}

3、Handler post方法的使用

new Handler().post(Runnable r)
new Handler().postAtFrontOfQueue(Runnable r);
new Handler().postAtTime(Runnable r, uptimeMillis);
new Handler().postAtTime(Runnable r, token, uptimeMillis);
new Handler().postDelayed(Runnable r, delayMillis);

Handler執行post方法會將參數Runnable對象,設置成Message的callback屬性Message消息對象加入隊列,如下:

Handler-gt;post-gt;Message.callback=r-gt;join MessageQueue

該Runnable對象的run方法會在UI線程中執行,當取出Message對象時判斷出該Message的callback不為null,于是調用handleCallback(msg)方法,該方法內部執行callback.run()方法。因為未開啟新的線程,所以run方法內部不能執行耗時操作。

如有問題懇請指正,謝謝!

END.


Tags: 線程 安卓開發

文章來源:http://blog.csdn.net/magic_jss/article/details/529


ads
ads

相關文章
ads

相關文章

ad