成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Handler 使用詳解

sihai / 1126人閱讀

摘要:機(jī)制處理的個(gè)關(guān)鍵對(duì)象線程之間傳遞的消息,可以攜帶一些簡(jiǎn)單的數(shù)據(jù)供子線程與主線程進(jìn)行交換數(shù)據(jù)。解決方法子線程通過(guò)發(fā)送消息給主線程,讓主線程處理消息,進(jìn)而更新。

極力推薦文章:歡迎收藏
Android 干貨分享

閱讀五分鐘,每日十點(diǎn),和您一起終身學(xué)習(xí),這里是程序員Android

本篇文章主要介紹 Android 開發(fā)中的部分知識(shí)點(diǎn),通過(guò)閱讀本篇文章,您將收獲以下內(nèi)容:

Handler 消息處理機(jī)制原理

Handler 機(jī)制處理的4個(gè)關(guān)鍵對(duì)象

Handler常用方法

子線程更新UI 異常處理

主線程給子線程發(fā)送消息的方法

子線程給主線程發(fā)送消息的方法

主、子 線程 互發(fā)消息方法

子線程方法中調(diào)用主線程更新UI的方法

HandlerAndroid中用來(lái)更新UI 的一套消息處理機(jī)制。Handler 允許線程間發(fā)送MessageRunnable對(duì)象進(jìn)行通信。在Android中UI修改只能通過(guò)UI Thread,子線程不能更新UI。如果子線程想更新UI,需要通過(guò) Handler 發(fā)送消息給主線程,進(jìn)而達(dá)到更新UI的目的。

Handler 簡(jiǎn)介 繼承關(guān)系如下:
java.lang.Object
   ?    android.os.Handler
1. Handler 消息處理機(jī)制原理

當(dāng)Android 應(yīng)用程序創(chuàng)建的時(shí)候,系統(tǒng)會(huì)給每一個(gè)進(jìn)程提供一個(gè)Looper ,Looper 是一個(gè)死循環(huán),它內(nèi)部維護(hù)一個(gè)消息隊(duì)列,Looper 不停的從消息隊(duì)列中取Message,取到的消息就發(fā)送給handler,最后Handler 根據(jù)接收的消息去修改UI等。

2. Handler 機(jī)制處理的4個(gè)關(guān)鍵對(duì)象 1.Message

線程之間傳遞的消息,可以攜帶一些簡(jiǎn)單的數(shù)據(jù)供子線程與主線程進(jìn)行交換數(shù)據(jù)。

2.Message Queue

存放通過(guò)Handler 發(fā)送的 Message 的消息隊(duì)列,每一個(gè)線程只有一個(gè)消息隊(duì)列。

3.Handler

消息處理者,主要用于發(fā)送跟處理消息。

主要功能:
發(fā)送消息SendMessage()
處理消息 HandleMessage()

4.Looper

內(nèi)部包含一個(gè)死循環(huán)的MessageQueue,用于存儲(chǔ)handler 發(fā)送的Message,Looper則是不斷的從消息隊(duì)列中取消,如果有消息就取出發(fā)送給Handler 處理,沒有則阻塞。

總結(jié):

Handler 負(fù)責(zé)發(fā)送MessageMessage QueueLooper負(fù)責(zé)從Message Queue 遍歷Message ,然后直接把遍歷的消息回傳給Handler 自己,通過(guò)Handler 自身的handleMessage處理更新UI等操作。

3. Handler常用方法 1.Runnable對(duì)象

post(Runnable)

使用方法舉例:

    public void BtnRunnableMethod(View view) {
        // 1.Runnable 對(duì)象
        RunnableHandlderMethod();
    }

    /**
     * Runnable 對(duì)象更新 UI 
     * **/
    private Handler mRunnableHandler = new Handler();
    public void RunnableHandlderMethod() {
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);

                    mRunnableHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            ((Button) findViewById(R.id.btn_runnable))
                                    .setText("Runnable");
                        }
                    });

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }.start();
    }

postAtTime(Runnable, long)

postDelayed(Runnable, long)

2. Message 對(duì)象

sendEmptyMessage(int)

使用方法舉例:

    public void BtnMessageThreadMethod(View view) {
        // 2.Message 對(duì)象
        new MessageHandlerThreadMethod("子線程不能更新UI").start();
    }
    /**
     * Message 對(duì)象舉例
     * ***/
    private int mCount = 0;
    private Handler mMessageHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            ((Button) findViewById(R.id.btn_thread)).setText("" + mCount);
        }
    };

    class MessageHandlerThreadMethod extends Thread {

        String mString;

        public MessageHandlerThreadMethod(String str) {
            mString = str;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {

                }

                mCount++;
                mMessageHandler.sendEmptyMessage(0);
            }

        }
    }

sendMessage(Message)

使用方法舉例:

public void BtnMessageObjMethod(View view) {
        HandlerMessageObjMethods();
    }

    /***
     * handler sendmessage 處理方法
     * **/
    private Handler mHandlerMessageObj = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            ((Button) findViewById(R.id.btn_message)).setText("arg1:"
                    + msg.arg1 + "
" + msg.obj);
        }
    };

    private void HandlerMessageObjMethods() {
        new Thread() {
            @Override
            public void run() {

                try {
                    Thread.sleep(1000);
                    // Message message = new Message();
                    Message message = mHandlerMessageObj.obtainMessage();

                    message.arg1 = 100;

                    Person person = new Person();
                    person.name = "Lucy";
                    person.age = 12;

                    message.obj = person;
                    mHandlerMessageObj.sendMessage(message);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    class Person {

        public int age;
        public String name;

        public String toString() {
            return "Name=" + name + "
 Age=" + age;
        }

    }

sendMessageAtTime(Message, long),

sendMessageDelayed(Message, long)

3.接收、處理Message

handleMessage(Message)

使用方法舉例:

    private Handler mMessageHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            ((Button) findViewById(R.id.btn_thread)).setText("" + mCount);
        }
    };
4. 子線程更新UI 異常處理

子線程不能更新UI,如果在子線程中更新UI,會(huì)出現(xiàn)CalledFromWrongThreadException 異常。

CalledFromWrongThreadException

解決方法:

子線程通過(guò)Handler 發(fā)送消息給主線程,讓主線程處理消息,進(jìn)而更新UI。

5. 主線程給子線程發(fā)送消息的方法

此例子中子線程通過(guò)Looper不斷遍歷主線程發(fā)送的消息,Looper 使用方法如下:

準(zhǔn)備Looper 輪詢器

Looper.prepare();

Handler 處理遍歷消息

Handler mHandler = new Handler()

遍歷消息隊(duì)列

Looper.loop();

Looper 使用方法如下:

    // 自定義 Loop 線程 ---> 不停的處理主線程發(fā)的消息
    class ChildLooperThread extends Thread {
        @Override
        public void run() {
            // 1.準(zhǔn)備成為loop線程
            Looper.prepare();
            // 2.處理消息
            mMainHandler = new Handler() {
                // 處理消息
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                            ... ...
                        }
                    });
                }
            };
            // 3.Loop循環(huán)方法
            Looper.loop();
        }

    }

主線程發(fā)送消息給子線程 的使用例子如下:

啟動(dòng) 子線程,并再啟動(dòng)后發(fā)送消息

    public void BtnMainMessageMethod(View view) {
        // 點(diǎn)擊主線程 按鈕,啟動(dòng)子線程,并在子線程啟動(dòng)后發(fā)送消息
        Message msg = new Message();
        msg.obj = "主線程:這是我攜帶的信息";
        if (mMainHandler != null) {
            // 2.主線程發(fā)送消息
            mMainHandler.sendMessage(msg);
        } else {
            Toast.makeText(getApplicationContext(), "開啟子線程輪詢消息,請(qǐng)?jiān)俅吸c(diǎn)擊發(fā)送消息",
                    Toast.LENGTH_SHORT).show();
            // 1.開啟輪詢線程,不斷等待接收主線成消息
            new ChildLooperThread().start();
        }
    }

子線程啟動(dòng),不停的變量主線程發(fā)送的消息

    private Handler mMainHandler;
    String mMainMessage;

    // 自定義 Loop 線程 ---> 不停的處理主線程發(fā)的消息
    class ChildLooperThread extends Thread {
        @Override
        public void run() {
            // 1.準(zhǔn)備成為loop線程
            Looper.prepare();
            // 2.處理消息
            mMainHandler = new Handler() {
                // 處理消息
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    mMainMessage = (String) msg.obj;
                    Log.i("TAG", "子線程:從主線程中接受的消息為:
" + mMainMessage);
                    // 使用 runOnUiThread 在主線程中更新UI
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            ((Button) findViewById(R.id.btn_main_message))
                                    .setText(mMainMessage);
                        }
                    });
                }
            };
            // 3.Loop循環(huán)方法
            Looper.loop();
        }

    }
6. 子線程給主線程發(fā)送消息的方法

1.子線程發(fā)送消息給主線程方法

    public void BtnChildMessageMethod(View view) {

        new Thread() {
            public void run() {
                while (mCount < 100) {
                    mCount++;
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    /**
                     * 利用handler 對(duì)象發(fā)送消息 Message msg=Message.obtain(); Message
                     * msg=new Message(); 獲取一個(gè)消息對(duì)象message
                     * */
                    Message msg = Message.obtain();
                    // 消息標(biāo)記
                    msg.what = 1;
                    // 傳遞整型值msg.obj="傳遞object數(shù)據(jù)"
                    msg.arg1 = mCount;
                    Log.i("TAG", "count 值=" + mCount);
                    if (mhandler != null) {
                        mhandler.sendMessage(msg);
                    }
                }
            }
        }.start();
    }

2.主線程接收并處理消息的方法

// 定義一個(gè)handler 主線程 接收子線程發(fā)來(lái)的信息
    private Handler mhandler = new Handler() {
        // 處理消息的方法
        public void handleMessage(android.os.Message msg) {

            switch (msg.what) {
            case 1:
                int value = msg.arg1;
                Log.i("TAG", "value值=" + value);
                ((Button) findViewById(R.id.btn_child_message)).setText("當(dāng)前值="
                        + value);
                break;

            default:
                break;
            }
        }

    };
7. 主、子 線程 互發(fā)消息方法

主要實(shí)現(xiàn)主、子線程每隔1s中通信一次

實(shí)現(xiàn)打印Log如下:

實(shí)現(xiàn)方法如下:

啟動(dòng)子線程并發(fā)送給主線程消息

    public void BtnMainChildMessageMethod(View view) {

        // 創(chuàng)建 名稱為currentThread 子線程
        HandlerThread mChildThread = new HandlerThread("ChildThread");
        mChildThread.start();
        mChildHandler = new Handler(mChildThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {

                Log.i("TAG", "主線程對(duì)我說(shuō):" + msg.obj);

                // 子線程攜帶的消息
                Message message = new Message();
                message.obj = Thread.currentThread() + "我是子線程,小樣,讓我聽你的沒門";
                // 向主線程發(fā)送消息
                mainhandler.sendMessageDelayed(message, 1000);
            }
        };
        // 主線成發(fā)送空消息,開啟通信
        mainhandler.sendEmptyMessage(1);
    }

2.主線程接收并處理子線程發(fā)送的消息

    // 創(chuàng)建主線程
    private Handler mainhandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            Log.i("TAG", "子線程對(duì)我說(shuō):" + msg.obj);

            // 主線成攜帶的消息內(nèi)容
            Message message = new Message();
            message.obj = Thread.currentThread() + "我是主線程:小子你得聽我的。";

            // 向子線程發(fā)送消息
            mChildHandler.sendMessageDelayed(message, 1000);
        }
    };
8.子線程方法中調(diào)用主線程更新UI的方法 Activity 中 可以使用 runOnUiThread(Runnable)
                    // 使用 runOnUiThread 在主線程中更新UI
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            ((Button) findViewById(R.id.btn_main_message))
                                    .setText(mMainMessage);
                        }
                    });
子線程使用 Handler.post(Runnable)
                    mRunnableHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            ((Button) findViewById(R.id.btn_runnable))
                                    .setText("Runnable");
                        }
                    });
View.post()
                            ((Button) findViewById(R.id.btn_runnable)).post(new Runnable() {
                                
                                @Override
                                public void run() {
                                    // TODO Auto-generated method stub
                                    ((Button) findViewById(R.id.btn_runnable)).setText("View.post()方法使用");
                                }
                            });
Handler.sendMessage(Message)
    public void BtnMainMessageMethod(View view) {
        // 點(diǎn)擊主線程 按鈕,啟動(dòng)子線程,并在子線程啟動(dòng)后發(fā)送消息
        Message msg = new Message();
        msg.obj = "主線程:這是我攜帶的信息";
        if (mMainHandler != null) {
            // 2.主線程發(fā)送消息
            mMainHandler.sendMessage(msg);
            }
}
9.移除Handler 發(fā)送的消息方法

1.移除 handler 發(fā)送的所有消息

private Handler mChildHandler;
mChildHandler.removeCallbacksAndMessages(null);

2.移除 指定消息

private Handler mainhandler;
mainhandler.removeMessages(what);

至此,本篇已結(jié)束,如有不對(duì)的地方,歡迎您的建議與指正。同時(shí)期待您的關(guān)注,感謝您的閱讀,謝謝!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/75832.html

相關(guān)文章

  • js事件詳解二:鼠標(biāo)和滾輪事件

    摘要:在級(jí)事件中定義了個(gè)鼠標(biāo)事件,分別是。取消鼠標(biāo)事件的默認(rèn)行為還會(huì)影響其他事件,因?yàn)槭髽?biāo)事件與其他事件是密不可分的關(guān)系。同樣的,和支持這個(gè)事件。兼容各個(gè)瀏覽器的事件監(jiān)聽對(duì)象該對(duì)象封裝了和級(jí)事件的常用事件函數(shù)。 概述 鼠標(biāo)事件是web開發(fā)中最常用的一類事件,畢竟鼠標(biāo)還是最主要的定位設(shè)備。在DOM3級(jí)事件中定義了9個(gè)鼠標(biāo)事件,分別是:click,dbclick,mousedown,mousee...

    Lucky_Boy 評(píng)論0 收藏0
  • Handler詳解

    我們?cè)趎ew Handler()時(shí)候,實(shí)際上調(diào)用的是兩個(gè)參數(shù)的構(gòu)造方法,我們看下 public Handler() { this(null, false); } public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { fina...

    Caizhenhao 評(píng)論0 收藏0
  • js事件詳解

    摘要:事件流事件流描述的是從頁(yè)面中接收事件的順序。其次,必須事先指定所有事件處理程序而導(dǎo)致的訪問次數(shù),會(huì)延遲整個(gè)頁(yè)面的交互就緒時(shí)間。 1.事件流 事件流描述的是從頁(yè)面中接收事件的順序。 1.1 事件冒泡 IE中的事件流叫做冒泡,即時(shí)間最開始由最具體的元素接收,然后逐級(jí)向上傳播到較為不具體的節(jié)點(diǎn),直到傳播到document對(duì)象。例: Event Exampple ...

    BDEEFE 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<