Android Handler使用案例詳解
什么是Handler?
Handler可以發(fā)送和處理消息對象或Runnable對象,這些消息對象和Runnable對象與一個線程相關(guān)聯(lián)。每個Handler的實例都關(guān)聯(lián)了一個線程和線程的消息隊列。當(dāng)創(chuàng)建了一個Handler對象時,一個線程或消息隊列同時也被創(chuàng)建,該Handler對象將發(fā)送和處理這些消息或Runnable對象。
handler類有兩種主要用途:
- 執(zhí)行Runnable對象,還可以設(shè)置延遲。
- 兩個線程之間發(fā)送消息,主要用來給主線程發(fā)送消息更新UI。
為什么要用Handler
解決多線程并發(fā)問題,假設(shè)如果在一個activity中,有多個線程去更新ui,并且都沒有加鎖機制,那界面顯示肯定會不正常。于是andoird官方就封裝了一套更新ui的機制,也可以用handler來實現(xiàn)多個線程之間的消息發(fā)送。
如何使用Handler
handler常用的方法有以下這些:
post(Runnable) postAtTime(Runnable,long) postDelayed(Runnable,long) sendEmptyMessage(int) sendMessage(Message) sendMessageAtTime(Message,long) sendMessageDelayed(Message,long)
我們可以看到這些方法主要分為兩類,一種是傳入一個Runnable對象,一種是傳入一個Message對象。
用代碼來學(xué)習(xí)post一個Runnable對象
先創(chuàng)建Handler對象,直接new一個就行
private Handler handler=new Handler();
實現(xiàn)Runnable接口,用匿名實現(xiàn)方式,重寫run方法,就打印一個字符串。
private Runnable runnable=new Runnable() { @Override public void run() { Log.i("MainActivity","Handler Runnable"); } };
然后我們調(diào)用handler的post方法,這里需要注意的是,post一個Runnable對象,底層用的是回調(diào),不會開啟一個新的線程,所有Runnable的run方法還是在主線程里面。是可以更新UI的。
handler.post(runnable);//執(zhí)行 handler.postDelayed(runnable,2000);//延遲2秒后執(zhí)行
運行程序,控制臺打印的log如下:
05-18 19:17:14.901 17750-17750/com.ansen.handler I/MainActivity: Handler Runnable 05-18 19:17:16.901 17750-17750/com.ansen.handler I/MainActivity: Handler Runnable
從上面的log我們可以看到兩條Log的時間相差兩秒。這是因為我們用postDelayed方法的時候第二個參數(shù)設(shè)置了兩秒的延遲。
使用sendMessage方法傳遞消息
從方法的名字上我們可以理解用來發(fā)送消息,這個方法在android中使用頻率比較高,因為在Android中多線程中是不能更新UI的,必須要通過Handler把消息傳遞給UI線程,才能更新UI。當(dāng)然也可以用Handler來兩個子線程發(fā)送消息。
我們給activity_main文件中TextView控件設(shè)置一個id,然后在MainActivity中查找這個控件,在多線程的for循環(huán)中給TextView賦值。增加后的代碼如下:
textview= (TextView) findViewById(R.id.textview); new Thread(new Runnable(){ @Override public void run(){ for(int i=1;i<=100;i++){ Log.i("MainActivity","當(dāng)前值是:"+i); textview.setText("當(dāng)前值是:"+i); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start();
重新運行代碼,程序奔潰??刂婆_打印如下log:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6024) at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:820)
這是因為在android中不能在多線程中更新UI造成的。
每個應(yīng)用啟動的時候,Android會啟動一個對應(yīng)的主線程用來處理UI相關(guān)的事情,例如用戶的按鍵事件,用戶接觸屏幕的事件以及屏幕繪圖事件,并把相關(guān)的事件分發(fā)到對應(yīng)的組件進行處理,所以主線程通常又被叫做UI線程。
這個時候我們就會用到Android的Handle類,Handle可以幫我們解決多線程不能更新UI問題,這里我們只要知道使用這個類就行,在后面我們會詳細介紹它的原理。
接下來我們看如何用handler在主線程中接受子線程的消息,并且更新UI。首先new一個Handler的時候?qū)崿F(xiàn)他的handleMessage方法,修改后的代碼如下:
private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what==UPDATE_UI){ textview.setText("當(dāng)前值是:"+msg.obj); } } };
我們可以看到把更新TextView的代碼放到這里來了,并且用到handleMessage的msg參數(shù)。這個對象我們常用的一般就兩個屬性,what就是一個標(biāo)示,我們發(fā)送消息的時候必需要指定值。obj:發(fā)送消息的參數(shù)。
再來看看多線程的run方法做了哪些改動,首先調(diào)用obtainMessage方法,這個方法呢是從消息池里面返回一個Message對象,如果消息池沒有才會創(chuàng)建對象,這樣避免一直去new Message對象。message對象有what屬性是必需要賦值的,是一個int類型。前面我們講到過了,是一個標(biāo)示。obj是發(fā)送消息用來傳參,這里我們傳入的是i的值。最后調(diào)用handler.sendMessage(message)方法。然后我們handler的handleMessage方法就會回調(diào)。
new Thread(new Runnable(){ @Override public void run(){ for(int i=1;i<=100;i++){ Log.i("MainActivity","當(dāng)前值是:"+i); Message message=handler.obtainMessage(); message.what=UPDATE_UI; message.obj=i; handler.sendMessage(message); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start();
還有sendEmptyMessage跟sendMessageDelayed方法我就不一一給大家解釋了,有興趣的朋友自己去實現(xiàn)一下。
到此這篇關(guān)于Android Handler使用案例詳解的文章就介紹到這了,更多相關(guān)Android Handler使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
android開發(fā)環(huán)境搭建詳解(eclipse + android sdk)
這篇文章主要介紹了android開發(fā)環(huán)境搭建詳解(eclipse + android sdk),需要的朋友可以參考下2014-05-05Android下錄制App操作生成Gif動態(tài)圖的全過程
這篇文章主要為大家分享了Android下錄制App操作生成Gif動態(tài)圖的全過程,感興趣的小伙伴們可以參考一下2016-01-01Android編程實現(xiàn)Home鍵的屏蔽,捕獲與修改方法
這篇文章主要介紹了Android編程實現(xiàn)Home鍵的屏蔽,捕獲與修改方法,實例分析了使用onAttachedToWindow捕獲Home鍵的相關(guān)技巧,需要的朋友可以參考下2016-06-06使用ListView實現(xiàn)網(wǎng)上訂餐首頁
這篇文章主要為大家詳細介紹了使用ListView實現(xiàn)網(wǎng)上訂餐首頁,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-01-01