日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android之HandlerThread源码分析和简单使用(主线程和子线程通信、子线程和子线程通信)

發(fā)布時間:2023/12/4 Android 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android之HandlerThread源码分析和简单使用(主线程和子线程通信、子线程和子线程通信) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1、先熟悉handler方式實現(xiàn)主線程和子線程互相通信方式,子線程和子線程的通信方式

????? 如果不熟悉或者忘記了,請參考我的這篇博客???? Android之用Handler實現(xiàn)主線程和子線程互相通信以及子線程和子線程之間的通信 ??? http://blog.csdn.net/u011068702/article/details/75577005

?

?

?

2、貼上簡單HandlerThread簡單使用(主線程和子線程通信、子線程和子線程通信)的例子

1、activity_main.xml文件

?

<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="com.example.handler.MainActivity1" ><Buttonandroid:id="@+id/button1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="ParentToChile" /><Buttonandroid:layout_below="@+id/button1"android:id="@+id/button2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="ChileToParent" /><Buttonandroid:layout_below="@+id/button2"android:id="@+id/button3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="ChileToChile" /></RelativeLayout>

?

?

?

2、MainActivity.java文件

?

package com.example.handler;import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button;public class MainActivity extends ActionBarActivity {public static final String TAG = "HandlerTest";public HandlerThread mHandlerThread;public Handler mChileHandler;public Handler mHandlerCToP = new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);int id = (int) Thread.currentThread().getId();Log.d(TAG, "mHandlerCToP currentThread id is:" + id);}};public Button mButtonPtoC;public Button mButtonCtoP;public Button mButtonCtoC;public Handler mHandler = new Handler();public Handler mHandlerCtoC = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);int id = (int) Thread.currentThread().getId();Log.d(TAG, "onCreate currentThread id is:" + id);initUIAndThread();}public void initUIAndThread() {mHandlerThread = new HandlerThread("chenyu");mHandlerThread.start();mHandler = new Handler(mHandlerThread.getLooper()) {@Overridepublic void handleMessage(Message msg) {int id = (int) Thread.currentThread().getId();Log.d(TAG, "initThread() mHandler handleMessage currentThread id is:" + id);switch(msg.what) {case 0:mHandlerCToP.post(new Runnable(){@Overridepublic void run() {int id = (int) Thread.currentThread().getId();Log.d(TAG, "initThread() mHandlerCToP post currentThread id is:" + id);mButtonPtoC.setText("chenyu");}});break;case 1:mHandlerCToP.post(new Runnable(){@Overridepublic void run() {int id = (int) Thread.currentThread().getId();Log.d(TAG, "initThread() mHandlerCToP post currentThread id is:" + id);mButtonCtoC.setText("chenyu");}});default:break;}}};mButtonPtoC = (Button)findViewById(R.id.button1);mButtonCtoP = (Button)findViewById(R.id.button2);mButtonCtoC = (Button)findViewById(R.id.button3);mButtonPtoC.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {int id = (int) Thread.currentThread().getId();Log.d(TAG, "mButtonPtoC currentThread id is:" + id);Log.d(TAG, "mHandlerPToc msg.what is 0");mHandler.sendEmptyMessage(0);}});mButtonCtoP.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {int id = (int) Thread.currentThread().getId();Log.d(TAG, "mButtonCtoP currentThread id is:" + id);Log.d(TAG, "mHandlerPToc msg.what is 0");mHandlerCToP.sendEmptyMessage(0);}});mButtonCtoC.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {new Thread(new Runnable(){@Overridepublic void run() {int id = (int) Thread.currentThread().getId();Log.d(TAG, "mButtonCtoC currentThread id is:" + id);Log.d(TAG, "mHandlerCToc msg.what is 1");mHandler.sendEmptyMessage(1);}}).start();}});}@Overrideprotected void onDestroy() {super.onDestroy();mHandlerThread.quit();} }

?

?

?

?

?

?

?

?

3、簡單分析例子

?? 1)、原始頁面效果

????????

??? 2)、控制臺初始化打印的線程ID

???????

?????? 分析:在onCreate方法里面打印的主線程的Id為1,有3個按鈕,分別是主線程向子線程發(fā)消息,子線程向主線程發(fā)消息,子線程和子線程發(fā)送消息,我們一開始就是對HandlerThread進(jìn)程初始化,其實它就是一個線程,后面會分析,然后執(zhí)行了start方法,我們把HandlerThread的looper對象傳遞給了Handler,之前的文章已分析,一個線程只能有一個looper對象,Handler擁有了HandlerThread的looper對象,就相當(dāng)于這個Handler在HandlerThread線程同樣的線程Id,可以理解為Handler 在子線程里面構(gòu)建,為什么我這里還有其它的Handler構(gòu)建,因為想搞清楚在哪里構(gòu)建屬于哪個線程以及子線程的handler是否可以更新UI,主線程構(gòu)建的handler是否可以更新UI,

??? 3)、依次點擊3個按鈕后控制臺打印的日志

???????

???? 我們可以看到在onCreate方法里面始化handler的時候傳遞了一個HandlerThread的looper對象,點擊第一個按鈕后后沒有開啟線程,當(dāng)前線程依然是主線程,handler發(fā)送了一個消息,然后初始化的handlMessage收到消息了,也就完成了主線程到子線程的通信,當(dāng)收到消息的時候,我們發(fā)現(xiàn)線程的id是6314,所以這個時候雖然是在onCreate里面構(gòu)建的handler里面的handlerMessage方法,但是線程Id是和HandlerThread線程Id是一樣的,然后初始化handler去更新界面,我們代碼是用mHandlerCtopP去更新的,因為它的初始化是在主線程構(gòu)建的,所以可以post可以更新UI,但是這個時候用擁有HandlerThread的looper對象的handler更新界面就會出問題,和子線程里面的handler去更新界面異常一樣,如下圖

?

然后點擊第二個按鈕,是現(xiàn)實子線程向主線程通信,我們發(fā)現(xiàn)點擊時間里面的線程Id,和handler收到消息的 handleMessage方法里面的線程id, 都是一樣,和主線程Id一樣,所以我們可以用這個handler直接post來更新UI,

點擊第三個按鈕,是實現(xiàn)子線程和子線程的通信,執(zhí)行點擊方法,我們開啟了一個線程,自然線程Id會和主線程的不一樣,為6318, handler收到消息的 handleMessage方法里面的線程id為6314,所以這里可以理解為為子線程線程里面構(gòu)建了handler,然后用主線程構(gòu)建的handler更新ui

?

?? 4)、依次點擊3個按鈕后手機(jī)效果

?????

?

?

?

?

4、HandlerThread.java源碼分析

??? 1、上源代碼

?????

package android.os;/*** Handy class for starting a new thread that has a looper. The looper can then be * used to create handler classes. Note that start() must still be called.*/ public class HandlerThread extends Thread {int mPriority;int mTid = -1;Looper mLooper;public HandlerThread(String name) {super(name);mPriority = Process.THREAD_PRIORITY_DEFAULT;}/*** Constructs a HandlerThread.* @param name* @param priority The priority to run the thread at. The value supplied must be from * {@link android.os.Process} and not from java.lang.Thread.*/public HandlerThread(String name, int priority) {super(name);mPriority = priority;}/*** Call back method that can be explicitly overridden if needed to execute some* setup before Looper loops.*/protected void onLooperPrepared() {}@Overridepublic void run() {mTid = Process.myTid();Looper.prepare();synchronized (this) {mLooper = Looper.myLooper();notifyAll();}Process.setThreadPriority(mPriority);onLooperPrepared();Looper.loop();mTid = -1;}/*** This method returns the Looper associated with this thread. If this thread not been started* or for any reason is isAlive() returns false, this method will return null. If this thread * has been started, this method will block until the looper has been initialized. * @return The looper.*/public Looper getLooper() {if (!isAlive()) {return null;}// If the thread has been started, wait until the looper has been created.synchronized (this) {while (isAlive() && mLooper == null) {try {wait();} catch (InterruptedException e) {}}}return mLooper;}public boolean quit() {Looper looper = getLooper();if (looper != null) {looper.quit();return true;}return false;}public boolean quitSafely() {Looper looper = getLooper();if (looper != null) {looper.quitSafely();return true;}return false;}/*** Returns the identifier of this thread. See Process.myTid().*/public int getThreadId() {return mTid;} }


1、我們知道這個類在android.os目錄下,然后繼承了Thread,也就是一個線程

?

2、構(gòu)造方法會傳一個字符串,這里可以隨便寫,只作為一個標(biāo)識而已,初始化的時候會調(diào)用start方法,然后會執(zhí)行run()方法

?

@Overridepublic void run() {mTid = Process.myTid();Looper.prepare();synchronized (this) {mLooper = Looper.myLooper();notifyAll();}Process.setThreadPriority(mPriority);onLooperPrepared();Looper.loop();mTid = -1;}


先執(zhí)行了Looper,prepare(),然后給當(dāng)前mLooper賦值,然后進(jìn)行Looper.loop(),進(jìn)行輪尋,這個代碼和標(biāo)準(zhǔn)的子線程用handler的方式差不多,也可以理解為這種方式的封裝,所以才能顯示子線程和子線程和主線程之間的通信,原理都是一樣。

?

3、getLooper()中有個wait(),這有什么用呢?因為的mLooper在一個線程中執(zhí)行創(chuàng)建,而我們的handler是在UI線程中調(diào)用getLooper()初始化的,必須等到mLooper創(chuàng)建完成,才能正確的返回。getLooper();wait(),notify()就是為了解決這兩個線程的同步問題。

?

4、這里有個退出的方法是

?

public boolean quit() {Looper looper = getLooper();if (looper != null) {looper.quit();return true;}return false;}


我之前寫代碼的時候,以為停止線程就調(diào)用了,mHandlerThread.stop()方法,后面沒發(fā)現(xiàn)什么問題,直到我們有個功能需要,從控制臺下發(fā)消息讓手機(jī)恢復(fù)默認(rèn)出場,函數(shù)執(zhí)行到了這里,導(dǎo)致進(jìn)程崩潰了,然后就發(fā)現(xiàn)這里有問題,需要調(diào)用mHandlerThread.quit()方法正常退出。

?

?

?

?

5、總結(jié)

????? 有時還需要頻繁更新UI,或則主線程向子線程通信,以及子線程和子線程經(jīng)常通信的時候,我們可以使用HandlerThread,如果哪里沒說清楚,或則講得有問題,歡迎點評

?

?

?

?

?

?

?????????

?????

?

?

?

?

總結(jié)

以上是生活随笔為你收集整理的Android之HandlerThread源码分析和简单使用(主线程和子线程通信、子线程和子线程通信)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。