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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

线程对象Android 开发之多线程处理、Handler 详解

發布時間:2024/8/23 Android 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线程对象Android 开发之多线程处理、Handler 详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

發一下牢騷和主題無關:

????

每日一道理
毅力,是千里大堤一沙一石的凝聚,一點點地累積,才有前不見頭后不見尾的壯麗;毅力,是春蠶吐絲一縷一縷的環繞,一絲絲地堅持,才有破繭而出重見光明的輝煌; 毅力,是遠航的船的帆,有了帆,船才可以到達成功的彼岸。

????

Android開發過程當中為什么要多線程

我們創立的Service、Activity以及Broadcast均是一個主線程處置,這里我們可以懂得為UI線程。但是在操作一些耗時操作時,比如I/O讀寫的大文件讀寫,數據庫操作以及網絡下載須要很長時間,為了不阻塞用戶界面,出現ANR的響應提示窗口,這個時候我們可以斟酌使用Thread線程來解決。

? Android中使用Thread線程會遇到哪些問題

對于從事過J2ME開發的程序員來講Thread比較簡單,直接匿名創立重寫run方法,調用start方法執行即可?;蛘邚腞unnable接口繼承,但對于Android平臺來講UI控件都沒有設計成為線程安全類型,所以須要引入一些同步的機制來使其刷新,這點Google在設計Android時倒是參考了下Win32的消息處置機制。

postInvalidate()方法

對于線程中的刷新一個View為基類的界面,可以使用postInvalidate()方法在線程中來處置,其中還供給了一些重寫方法比如postInvalidate(int left,int top,int right,int bottom)?來刷新一個矩形區域,以及延時執行,比如postInvalidateDelayed(long delayMilliseconds)或postInvalidateDelayed(long delayMilliseconds,int left,int top,int right,int bottom)?方法,其中第一個參數為毫秒,如下:

void

postInvalidate()

void

postInvalidate(int left, int top, int right, int bottom)

void

postInvalidateDelayed(long delayMilliseconds)

void

postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)

Handler

當然推薦的方法是通過一個Handler來處置這些,可以在一個線程的run方法中調用handler對象的postMessage或sendMessage方法來實現,Android程序外部維護著一個消息隊列,會輪訓處置這些,如果你是Win32程序員可以很好懂得這些消息處置,不過相對于Android來講沒有供給PreTranslateMessage這些干預外部的方法。

消息的處置者,handler負責將須要傳遞的信息封裝成Message,通過調用handler對象的obtainMessage()來實現。將消息傳遞給Looper,這是通過handler對象的sendMessage()來實現的。繼而由Looper將Message放入MessageQueue中。當Looper對象看到MessageQueue中含有Message,就將其廣播出去。該handler對象收到該消息后,調用相應的handler對象的handleMessage()方法對其停止處置。

?

Handler主要接受子線程發送的數據,并用此數據配合主線程更新UI.
??????當應用程序啟動時,Android首先會開啟一個主線程?(也就是UI線程) ,?主線程為管理界面中的UI控件,停止事件分發,比如說,你要是點擊一個?Button ,Android會分發事件到Button上,來響應你的操作。??如果此時須要一個耗時的操作,例如:聯網讀取數據,?或者讀取當地較大的一個文件的時候,你不能把這些操作放在主線程中,,如果你放在主線程中的話,界面會出現假死景象,如果5秒鐘還沒有實現的話,,會收到Android系統的一個錯誤提示? "強制關閉".??這個時候我們須要把這些耗時的操作,放在一個子線程中,因為子線程涉及到UI更新,,Android主線程是線程不安全的,也就是說,更新UI只能在主線程中更新,子線程中操作是危險的.這個時候,Handler就出現了,來解決這個復雜的問題,?由于Handler運行在主線程中(UI線程中),??它與子線程可以通過Message對象來傳遞數據,這個時候,Handler就承擔著接受子線程傳過來的(子線程用sedMessage()方法傳弟)Message對象,(里面包括數據)? ,把這些消息放入主線程隊列中,配合主線程停止更新UI。


Handler一些特點:handler可以分發Message對象和Runnable對象到主線程中,每一個Handler實例,都會綁定到創立他的線程中(一般是位于主線程),
??????它有兩個作用: (1)安排消息或Runnable在某個主線程中某個地方執行

?????????????????????????? (2)安排一個動作在不同的線程中執行
??????? Handler平分發消息的一些方法
??????? post(Runnable)
??????? postAtTime(Runnable,long)
??????? postDelayed(Runnable long)
??????? sendEmptyMessage(int)
??????? sendMessage(Message)
??????? sendMessageAtTime(Message,long)
??????? sendMessageDelayed(Message,long)
??????以上post類方法答應你排列一個Runnable對象到主線程隊列中,sendMessage類方法,答應你安排一個帶數據的Message對象到隊列中,等待更新.

Handler實例
????//?子類須要繼承Hendler類,并重寫handleMessage(Message msg)?方法,用于接受線程數據
???? //?以下為一個實例,它實現的功能為?:通過線程修改界面Button的內容

public class MyHandlerActivity extends Activity {

??? Button button;

??? MyHandler myHandler;

??? protected void onCreate(Bundle savedInstanceState) {

??????? super.onCreate(savedInstanceState);

??????? setContentview(R.layout.handlertest);

??????? button = (Button) findViewById(R.id.button);

??????? myHandler = new MyHandler();

??????? //當創立一個新的Handler實例時,它會綁定到當前線程和消息的隊列中,開始分發數據

??????? // Handler有兩個作用, (1) :定時執行Message和Runnalbe對象

??????? // (2):讓一個動作,在不同的線程中執行.

??????? //它安排消息,用以下方法

??????? // post(Runnable)

??????? // postAtTime(Runnable,long)

??????? // postDelayed(Runnable,long)

??????? // sendEmptyMessage(int)

??????? // sendMessage(Message);

??????? // sendMessageAtTime(Message,long)

??????? // sendMessageDelayed(Message,long)

??????? //以上方法以?post掃尾的答應你處置Runnable對象

??????? //sendMessage()答應你處置Message對象(Message里可以包括數據,)

??????? MyThread m = new MyThread();

??????? new Thread(m).start();

??? }

??? /**

???? *接受消息,處置消息?,此Handler會與當前主線程一塊運行

???? * */

??? class MyHandler extends Handler {

??????? public MyHandler() {

??????? }

??????? public MyHandler(Looper L) {

??????????? super(L);

??????? }

??????? //子類必須重寫此方法,接受數據

??????? @Override

??????? public void handleMessage(Message msg) {

??????????? // TODO Auto-generated method stub

??????????? Log.d("MyHandler", "handleMessage......");

??????????? super.handleMessage(msg);

??????????? //此處可以更新UI

??????????? Bundle b = msg.getData();

??????????? String color = b.getString("color");

??????????? MyHandlerActivity.this.button.append(color);

??????? }

??? }

??? class MyThread implements Runnable {

??????? public void run() {

??????????? try {

??????????????? Thread.sleep(10000);

??????????? } catch (InterruptedException e) {

??????????????? // TODO Auto-generated catch block

??????????????? e.printStackTrace();

??????????? }

??????????? Log.d("thread.......", "mThread........");

??????????? Message msg = new Message();

??????????? Bundle b = new Bundle();//存放數據

??????????? b.putString("color", "我的");

??????????? msg.setData(b);

??????????? MyHandlerActivity.this.myHandler.sendMessage(msg); //向Handler發送消息,更新UI

??????? }

??? }
}

? Looper

其實Android中每一個Thread都隨著一個Looper,Looper可以幫助Thread維護一個消息隊列,昨天的問題?Can't create handler inside thread?錯誤?一文中提到這一觀點,但是Looper和Handler沒有什么關系,我們從開源的代碼可以看到Android還供給了一個Thread繼承類HanderThread可以幫助我們處置,在HandlerThread對象中可以通過getLooper方法獲得一個Looper對象控制句柄,我們可以將其這個Looper對象映射到一個Handler中去來實現一個線程同步機制,Looper對象的執行須要初始化Looper.prepare方法就是昨天我們看到的問題,同時推出時還要釋放資源,使用Looper.release方法。

Looper是MessageQueue的管理者。每一個MessageQueue都不能脫離Looper而存在,Looper對象的創立是通過prepare函數來實現的。同時每一個Looper對象和一個線程關聯。通過調用Looper.myLooper()可以獲得當前線程的Looper對象?
創立一個Looper對象時,會同時創立一個MessageQueue對象。除了主線程有默許的Looper,其他線程默許是沒有MessageQueue對象的,所以,不能接受Message。如須要接受,自己定義一個Looper對象(通過prepare函數),這樣該線程就有了自己的Looper對象和MessageQueue數據結構了。?
Looper從MessageQueue中取出Message然后,交由Handler的handleMessage停止處置。處置實現后,調用Message.recycle()將其放入Message Pool中。

Message

對于Android中Handler可以傳遞一些內容,通過Bundle對象可以封裝String、Integer以及Blob二進制對象,我們通過在線程中使用Handler對象的??? sendEmptyMessage或sendMessage方法來傳遞一個Bundle對象到Handler處置器。對于Handler類供給了重寫方法handleMessage(Message msg)?來判斷,通過msg.what來區分每條信息。將Bundle解包來實現Handler類更新UI線程中的內容實現控件的刷新操作。相關的Handler對象有關消息發送sendXXXX相關方法如下,同時還有postXXXX相關方法,這些和Win32中的道理基本一致,一個為發送后直接返回,一個為處置后才返回。

Message:消息對象,Message Queue中的存放的對象。一個Message Queue中包括多個Message。?Message實例對象的取得,通常使用Message類里的靜態方法obtain(),該方法有多個重載版本可供選擇;它的創立并不一定是直接創立一個新的實例,而是先從Message Pool(消息池)中看有沒有可用的Message實例,存在則直接取出返回這個實例。如果Message Pool中沒有可用的Message實例,則才用給定的參數創立一個Message對象。調用removeMessages()時,將Message從Message Queue中刪除,同時放入到Message Pool中。除了上面這種方式,也可以通過Handler對象的obtainMessage()獲得一個Message實例。

final boolean

sendEmptyMessage(int what)

final boolean

sendEmptyMessageAtTime(int what, long uptimeMillis)

final boolean

sendEmptyMessageDelayed(int what, long delayMillis)

final boolean

sendMessage(Message?msg)

final boolean

sendMessageAtFrontOfQueue(Message?msg)

boolean

sendMessageAtTime(Message?msg, long uptimeMillis)

final boolean

sendMessageDelayed(Message?msg, long delayMillis)

MessageQueue

是一種數據結構,見名知義,就是一個消息隊列,存放消息的地方。每一個線程最多只可以擁有一個MessageQueue數據結構。?
創立一個線程的時候,并不會自動創立其MessageQueue。通常使用一個Looper對象對該線程的MessageQueue停止管理。主線程創立時,會創立一個默許的Looper對象,而Looper對象的創立,將自動創立一個Message Queue。其他非主線程,不會自動創立Looper,要須要的時候,通過調用prepare函數來實現。?
java.util.concurrent對象分析

對于過去從事Java開發的程序員不會對Concurrent對象感到陌生吧,他是JDK 1.5以后新增的重要特性作為掌上設備,我們不提倡使用該類,斟酌到Android為我們已經設計好的Task機制,我們這里Android開發網對其不做過多的贅述。

Task以及AsyncTask

在Android中還供給了一種有別于線程的處置方式,就是Task以及AsyncTask,從開源代碼中可以看到是針對Concurrent的封裝,開發人員可以方便的處置這些異步任務。?當然涉及到同步機制的方法和技巧還有很多,斟酌時間和篇幅問題不再做過多的描述。

文章結束給大家分享下程序員的一些笑話語錄: 一個合格的程序員是不會寫出 諸如 “摧毀地球” 這樣的程序的,他們會寫一個函數叫 “摧毀行星”而把地球當一個參數傳進去。

--------------------------------- 原創文章 By
線程和對象
---------------------------------

轉載于:https://www.cnblogs.com/jiangu66/archive/2013/05/28/3104983.html

總結

以上是生活随笔為你收集整理的线程对象Android 开发之多线程处理、Handler 详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。