① Android Studio Handler 用法
you should import "Android.os.Handler" to override the method "handleMessage".
② Android中Handler的使用方法
Handler在Android中主要是負責發送和處理消息。它的主要用途大致是下面兩個:
1)按計劃發送消息或執行某個Runnanble;
2)從其他線程中發送來的消息放入消息隊列中,避免線程沖突(常見於更新UI線程)
學寫一下,在UI線程中,系統已經有一個Activity來處理了,你可以再起若干個Handler來處理。在實例化Handler的時候,只要有Handler的指針,任何線程也都可以sendMessage。
Handler對於Message的處理是非同步處理的。一個Looper 只有處理完一條Message才會讀取下一條,所以消息的處理是阻塞形式的(handleMessage()方法里不應該有耗時操作,可以將耗時操作放在其他線程執行,操作完後發送Message(通過sendMessges方法),然後由handleMessage()更新UI)。
根據對視頻的學習寫了一個通過Button控制項啟動進度條(類似於下載等操作)的程序,簡單介紹一下,有兩個Button控制項,一個是開始,點擊之後會顯示一個進度條以每次十分之一的進度進行(一開始是隱藏的),另一個是停止,可以中斷進度。
java代碼:
1 package zzl.handleactivity;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.os.Handler;
6 import android.os.Message;
7 import android.view.Gravity;
8 import android.view.View;
9 import android.view.View.OnClickListener;
10 import android.widget.Button;
11 import android.widget.ProgressBar;
12 import android.widget.Toast;
13
14 public class Handler_01 extends Activity {
15
16 //聲明變數
17 private Button startButton=null;
18 private Button endButton=null;
19 private ProgressBar firstBar=null;
20 private Toast toast=null;
21 @Override
22 protected void onCreate(Bundle savedInstanceState) {
23 super.onCreate(savedInstanceState);
24 setContentView(R.layout.main);
25
26 //根據ID獲取對象
27 startButton =(Button)findViewById(R.id.startButton);
28 endButton=(Button)findViewById(R.id.endButton);
29 firstBar=(ProgressBar)findViewById(R.id.firstBar);
30 //給對象設置動作監聽器
31 startButton.setOnClickListener(new StartButtonListener());
32 endButton.setOnClickListener(new EndButtonListener());
33 }
34
35 class StartButtonListener implements OnClickListener{
36
37 @Override
38 public void onClick(View v) {
39 // TODO Auto-generated method stub
40 //一開始執行,加入到消息隊列,不延遲,
41 //然後馬上執行run方法
42 firstBar.setVisibility(View.VISIBLE);
43 firstBar.setMax(100);
44 handler.post(upRunnable);
45 toast=Toast.makeText(Handler_01.this, "運行開始", Toast.LENGTH_SHORT);
46 toast.setGravity(Gravity.CENTER, 0, 0);
47 toast.show();
48 }
49 }
50 class EndButtonListener implements OnClickListener{
51
52 @Override
53 public void onClick(View v) {
54 // TODO Auto-generated method stub
55 //停止
56 handler.removeCallbacks(upRunnable);
57 System.out.println("It's time to stop...");
58 }
59 }
60
61 //創建handler對象,在調用post方法
62 //非同步消息處理:將下載或者處理大數據等等單獨放到另一個線程
63 //更好的用戶體驗
64 Handler handler=new Handler(){
65
66 @Override
67 public void handleMessage(Message msg){
68 firstBar.setProgress(msg.arg1);
69 firstBar.setSecondaryProgress(msg.arg1+10);
70 //handler.post(upRunnable);
71 if(msg.arg1<=100) {
72 handler.post(upRunnable); //將要執行的線程放入到隊列當中
73 }else {
74 handler.removeCallbacks(upRunnable);
75 }
76 }
77 };
78
79 //聲明線程類:實現Runnable的介面
80 Runnable upRunnable=new Runnable() {
81
82 int i=0;
83 @Override
84 public void run() {//程序的運行狀態
85 // TODO Auto-generated method stub
86 //postDelayed方法:把線程對象加入到消息隊列中
87 // 隔2000ms(延遲)
88 System.out.println("It's time to start...");
89 i=i+10;
90 //獲取Message消息對象
91 Message msg=handler.obtainMessage();
92 //將msg對象的arg1(還有arg2)對象的值設置
93 //使用這兩個變數傳遞消息優點:系統消耗性能較少
94 msg.arg1=i;
95 try{
96 //設置當前顯示睡眠1秒
97 Thread.sleep(1000);
98 }catch(InterruptedException e){
99 e.printStackTrace();
100 }
101 //將msg對象加入到消息隊列當中
102 handler.sendMessage(msg);
103 if(i==100){//當值滿足時,將線程對象從handle中剔除
104 handler.removeCallbacks(upRunnable);
105 firstBar.setVisibility(View.GONE);
106 //臨時彈出
107
108 toast=Toast.makeText(Handler_01.this, "運行結束", Toast.LENGTH_SHORT);
109 toast.setGravity(Gravity.CENTER, 0, 0);
110 toast.show();
111 }
112 }
113 };
114 }
main.xml
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools"
3 android:orientation="vertical"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent"
6 tools:context=".Handler_01" >
7
8 <ProgressBar
9 android:id="@+id/firstBar"
10 style="?android:attr/progressBarStyleHorizontal"
11 android:layout_width="200dp"
12 android:layout_height="wrap_content"
13 android:visibility="gone"/>
14
15 <Button
16 android:id="@+id/startButton"
17 android:layout_width="wrap_content"
18 android:layout_height="wrap_content"
19 android:text="@string/start" />
20
21 <Button
22 android:id="@+id/endButton"
23 android:layout_width="wrap_content"
24 android:layout_height="wrap_content"
25 android:text="@string/end" />
26
27 </LinearLayout>
總結:
1)當點擊開始或者運行結束的時候,都會通過調用Toas彈出臨時窗口,Toast.makeText(Handler_01.this, "運行結束", Toast.LENGTH_SHORT),這一句一開始總是執行出錯,原因在於必須調用它的show方法才可以顯示出來,還可以通過設置它的位置來顯示;
2)在xml中 android:text="@string/end",則需要在layout下的string文件中敲寫相應的代碼
3)原本代碼有一些瑕疵,就是沒有下面這一段代碼:
1 if(msg.arg1<=100) {
2 handler.post(upRunnable); //將要執行的線程放入到隊列當中
3 }else {
4 handler.removeCallbacks(upRunnable);
5 }
這樣就導致了upRunnable的run方法出現了死循環,這樣,雖然程序UI本身沒有問題,但是內部卻又很大的缺陷
這是因為
1 if(i==100){//當值滿足時,將線程對象從handle中剔除
2 handler.removeCallbacks(upRunnable);
3 firstBar.setVisibility(View.GONE);
4 toast=Toast.makeText(Handler_01.this, "運行結束", Toast.LENGTH_SHORT);
5 toast.setGravity(Gravity.CENTER, 0, 0);
6 toast.show();
7 }
這一段代碼看似是把upRunnable線程從線程對象隊列中移除,但是再次之前又前執行了handler.sendMessage(msg);這句代碼
從而導致下面的代碼又被執行到
1 public void handleMessage(Message msg){
2 firstBar.setProgress(msg.arg1);
3 firstBar.setSecondaryProgress(msg.arg1+10);
4
5 }
這樣肯定會使upRunnable線程重新加入到線程對象隊列中,updateThread的run方法重復執行,這就導致了死循環。所以必須加上之前的那段代碼,通過判斷來控制循環終止。並且run方法中的if(i==100)的那段代碼也是可以不用的,不過我是寫了一些其他代碼就懶得優化了,這是後話了。
4) 剛剛大家看到我們可以通過敲寫System.out.println在logcat中顯示,一開始eclipse編譯器中是沒有,這是如何顯示出來的?
大家可以再window的show view中找到logCat(deprecated)通過下圖中綠色的「+」添加出來
然後顯示內容的時候,選擇右上角「V D I W E 」的I就可以比較清晰的顯示出來了,當然你也可以選擇另外一個logCat來顯示,方法類似。
5)實際上,Handler在默認情況下,和調用它的Activity是處於同一個線程的。 上述Handler的使用示例中,雖然聲明了線程對象,但是在實際調用當中它並沒有調用線程的start()方法,而是直接調用當前線程的run()方法。
如果要實現調用另一個新的線程,只要注釋post方法,然後加上這樣兩段代碼即可: Thread t = new Thread(r); t.start();
③ android中Handler的post方法的作用是什麼
在工作線程中執行耗時任務,當任務完成時,會返回UI線程,一般是更新UI。這時有兩種方法可以達到目的。
一種是handler.sendMessage。發一個消息,再根據消息,執行相關任務代碼。
另一種是handler.post(r)。r是要執行的任務代碼。意思就是說r的代碼實際是在UI線程執行的。可以寫更新UI的代碼。

(3)androidhandler的使用方法擴展閱讀
一個APK文件結構為:
1、META-INF (註:Jar文件中常可以看到);
2、res (註:存放資源文件的目錄) ;
3、AndroidManifest.xml (註:程序全局配置文件) ;
4、classes.dex (註:Dalvik位元組碼);
5、resources.arsc (註:編譯後的二進制資源文件)。
Android在運行一個程序時首先需要UnZip,然後類似Symbian那樣直接執行安裝,和Windows Mobile中的PE文件有區別,這樣做對於程序的保密性和可靠性不是很高,通過dexmp命令可以反編譯,但這樣做符合發展規律,微軟的 Windows Gadgets或者說WPF也採用了這種構架方式。
在Android平台中dalvik vm的執行文件被打包為apk格式,最終運行時載入器會解壓然後獲取編譯後androidmanifest.xml文件中的permission分支相關的安全訪問,但仍然存在很多安全限制,如果你將apk文件傳到/system/app文件夾下會發現執行是不受限制的。
參考資料來源:網路-Android
④ Android Handler機制 怎麼用
Handler對象與其調用者在同一線程中,如果在Handler中設置了延時操作,則調用線程也會堵塞。每個Handler對象都會綁定一個Looper對象,每個Looper對象對應一個消息隊列(MessageQueue)。如果在創建Handler時不指定與其綁定的Looper對象,系統默認會將當前線程的Looper綁定到該Handler上。
在主線程中,可以直接使用new Handler()創建Handler對象,其將自動與主線程的Looper對象綁定;在非主線程中直接這樣創建Handler則會報錯,因為Android系統默認情況下非主線程中沒有開啟Looper,而Handler對象必須綁定Looper對象。這種情況下,需先在該線程中手動開啟Looper(Looper.prepare()-->Looper.loop()),然後將其綁定到Handler對象上;或者通過Looper.getMainLooper(),獲得主線程的Looper,將其綁定到此Handler對象上。
Handler發送的消息都會加入到Looper的MessageQueue中。一說Handler包含兩個隊列:線程隊列和消息隊列;使用Handler.post()可以將線程對象加入到線程隊列中;使用Handler.sendMessage()可以將消息對象加入到消息隊列中。通過源碼分析證實,Handler只有一個消息隊列,即MessageQueue。通過post()傳進去的線程對象將會被封裝成消息對象後傳入MessageQueue。
使用post()將線程對象放到消息隊列中後,當Looper輪詢到該線程執行時,實際上並不會單獨開啟一個新線程,而仍然在當前Looper綁定的線程中執行,Handler只是調用了該線程對象的run()而已。如,在子線程中定義了更新UI的指令,若直接開啟將該線程執行,則會報錯;而通過post()將其加入到主線程的Looper中並執行,就可以實現UI的更新。
使用sendMessage()將消息對象加入到消息隊列後,當Looper輪詢到該消息時,就會調用Handler的handleMessage()來對其進行處理。再以更新UI為例,使用這種方法的話,就先將主線程的Looper綁定在Handler對象上,重載handleMessage()來處理UI更新,然後向其發送消息就可以了。
⑤ Android 為什麼使用Handler
在Android的UI開發中,我們經常會使用Handler來控制主UI程序的界面變化。有關Handler的作用,我們總結為:與其他線程協同工作,接收其他線程的消息並通過接收到的消息更新主UI線程的內容。
我們假設在一個UI界面上面,有一個按鈕,當點擊這個按鈕的時候,會進行網路連接,並把網路上的一個字元串拿下來顯示到界面上的一個 TextView上面,這時就出現了一個問題,如果這個網路連接的延遲過大,可能是10秒鍾甚至更長,那我們的界面將處於一直假死狀態,而如果這段時間超 過5秒鍾的話,程序會出現異常。
這時我們會想到使用線程來完成以上工作,即當按鈕被按下的時候新開啟一個線程來完成網路連接工作,並把得到的結果更新到UI上面。但是,這時候又會 出現另一個問題,在Android中,主線程是非線程安全的,也就是說UI的更新只能在本線程中完成,其他線程無法直接對主線程進行操作。
為了解決以上問題,Android設計了Handler機制,由Handler來負責與子線程進行通訊,從而讓子線程與主線程之間建立起協作的橋梁,使Android的UI更新的問題得到完美的解決。接下來舉例來詮釋Handler的基本使用方法。
Handler的工作原理
一般情況下,在主線程中我們綁定了Handler,並在事件觸發上面創建新的線程用於完成某些耗時的操作,當子線程中的工作完成之後,會對Handler發送一個完成的信號,而Handler接收到信號後,就進行主UI界面的更新操作。
2
Handler與子線程協作實例
1、創建Handler實現類,在主UI所在類中的內部類
class MyHandler extends Handler {
public MyHandler() { }
public MyHandler(Looper L) {
super(L);
}
// 重寫handleMessage方法,接受數據並更新UI
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//此處根據msg內容進行UI操作
}
}
2、子線程的實現
class MyThread implements Runnable {
public void run() {
Message msg = new Message();
Bundle b = new Bundle();
b.putString("cmd", "update");
msg.setData(b);
MainActivity.this.myHandler.sendMessage(msg);
//通知Handler更新UI
}
}
通過以上的兩個實現,我們只需要在MainActivity中聲明MyHandler實例對象就可以完成線程之間的通訊和界面的更新操作。
MyHandler myHandler = newMyHandler();
⑥ 能講講Android的Handler機制嗎
Android的Handler機制是通俗講為了互相發消息,一般是子線程給主線程發消息完成相應操作。
安卓中最常見的操作是子線程操作完事後得到數據想更新UI,安卓有規定不允許在子線程中刷新UI,所以Handler出現了。
使用和理解大致步驟。
創建全局Handler對象handler,然後在主線程中初始化它(一般在oncreate中),把它的handmessage裡面的方法重寫,這個方法是收到子線程發給它的消息後執行的邏輯。
在子線程中獲取數據,調用handler.sendmessage,把要發的消息放在message中。message會添加到Messagequue(消息隊列中,handler創建就帶的)。
3.對象handler被創建和初始化的時候,系統自動會啟動Handler.looper,也就是一個消息輪詢器,它不斷的去查看有沒有消息進入到Messagequue(消息隊列中),有就取出交給handler的handmessage去處理。//這段邏輯是系統自動執行,理解就行。*純手打,不騙人~~~
⑦ android中handler的使用
Handler這部分我也在用,模仿例子套著用,主要用於子線程向主程序發消息,讓Handler對象處理。你的疑問我也有,這new Handler(){},只是一瞬間就結束的,可它仍時刻監視著自已的消息以便隨時再處理,這似乎有點不符常規令人不解,但細想一下,這就象一個按鈕控制項對象,
你點擊一下,它就能響應一次點擊處理事件。
⑧ Android中Handler的主要作用是什麼通俗點,初學。
Handler的使用主要是android中無法在主線程(即UI線程)中訪問網路、無法在子線程中訪問UI線程元素。
一般是在子線程中訪問網路,然後使用Handler發送message通知主線程處理UI更新操作
⑨ C#寫Android應用時handler和message要怎麼用
handler的方法中有post();裡面的參數為Runnable類型,一般在主線程中建立handler,子線程向其發送消息,使其更新UI界面,在主線程中,可以通過post(),將Runnable()中的任務加入主線程的消息隊列中;
在子線程中,是沒有消息隊列的,需要自己創建,在主線程中,系統會幫我們創建一個消息隊列;
Looper負責消息的傳遞
這樣子線程就可以用post將Runnbale()加入到消息隊列中去,這樣主線程都可以向子線程發送消息了,如:按鈕(點擊後發送消息)
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();//Looper准備
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();//讓Looper動起來
}
}
原則是:先建立Handler,再發送消息,或者post();
Handler的函數在所有線程中均可使用,利用內部類實現;