編輯:關於android開發
什麼是Handler?
handler是Android給我們提供用來更新UI的一套機制,也是一套消息處理機制.
我們可以使用它發送消息,也可以通過它處理消息.
我們為什麼要使用Handler?
Android在設計的時候,就封裝了一套消息創建,傳遞,處理機制,如果不遵循這樣的機制,就沒有辦法更新UI,而且還會拋出異常信息.
例如:大家都知道,更新UI的操作一般都是放在main線程中,當我們需要在子線程中更新UI時,就需要使用到了Handler,雖然在子線程更新Ui的方法有好幾種,但內部實現原理基本都是通過Handler發送消息處理的,不要著急,下面會提到.
Handler的使用:
sendMessage()方法的使用:
package com.hnthgys.mytext;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView tv;
//創建main線程的Handler
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
tv.setText("我是通過handler發送消息更新的");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textview);
//開啟子線程
new Thread(){
@Override
public void run() {
super.run();
//例如此處我們正在執行一個耗時操作,執行完畢後發送消息更新ui
//發送一個空消息
handler.sendEmptyMessage(0);
//如果此處我們需要使用執行完耗時操作的數據,可以這樣寫
//Message msg = handler.obtainMessage();
//msg.obj = "數據";
//handler.sendMessage(msg);
}
}.start();
}
}
sendEmptyMessage(); 此方法和sendMessage使用一致,區別就是發送一個空消息.
sendMessageDelayed(); 發送一個延時執行的消息
post(Runnable);該方法可以在子線程中更新UI,該方法運行在main線程中
removeCallbacksAndMessages();移除回調和消息;例如:我們在使Handler輪播一些圖片時,想讓它停止輪播,就可以使用這個方法.android為什麼要設計只能通過handler來更新UI呢?
最根本的的目的就是解決多線程並發問題.假設如果在一個activity當中,有多個線程去更新UI,並且都沒有加鎖機制,那麼會產生什麼樣子的問題呢? 更新界面錯誤.
你可能會說,我可以使用加鎖的多線程啊,如果對更新UI的操作都進行加鎖處理的話,應用程序的性能會大大下降.
處於對以上問題的考慮,Android給我們提供了一套更新UI的機制,我們只需要遵循這樣的機制就可以了.
根本不用關心多線程的問題,所以更新UI的操作,都是在主線程的消息隊列當中去輪詢處理的.
Handler的原理是什麼呢?
一,Handler封裝了消息的發送,(主要包括消息發送給誰)
Looper(Handler內部自己的Looper)
1,內部包含一個消息隊列,也就是MessageQueue,所有的Handler發送消息
都走向這個消息隊列.
2,Looper.loop()方法,就是一個死循環,不斷的從MessageQueue中取消息,
如果有消息就處理消息,沒有消息就阻塞.
二,MessageQueue,就是一個消息隊列,可以添加消息,並處理消息.
三,Handler,內部會跟Lopper進行關聯,也就是說在Handler的
內部可以找到Looper,找到了Lopper也就找到 了MessageQueue,
在Handler中發送消息,其實就是向MessageQueue隊列中發送消息.
Handler原理總結:
Handler負責發送消息,Loooper負責接收Handler發送的消息,
並直接把消息回傳給Handler自己.
MessageQueue就是一個存儲消息的容器.
Handler使用中遇到的問題:
在非UI線程中更新UI,拋出的異常:
在子線程創建Handler,拋出的異常:
注意:當需要在子線程中創建Handler時,需要先創建一個Looper,因為子線程中沒有Looper對象
HandlerThread又是什麼?
當我們向創建一個與線程相關的Handler時,我們可以使用HandlerThread,來解決多線程的並發問題.
子線程與主線程如何互發消息:
主線程Handler向子線程發送消息(偽代碼)Android在子線程中更新UI的幾種方式:
使用圖片吧,以前做的筆記,看著感覺更加清晰..
非UI線程真的不能更新UI嗎?
答案是能,對.你沒有看錯,非UI線程也能更新UI.可能你會覺得我在扯淡,下面看一段代碼:
package com.hnthgys.mytext;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView tv;
//創建main線程的Handler
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textview);
//開啟子線程
new Thread(){
@Override
public void run() {
super.run();
//SystemClock.sleep(100);
tv.setText("我是在子線程中更新的UI");
}
}.start();
}
}
我把布局代碼也貼出來,
執行效果圖:
可能看到這,你已經目瞪口呆了,這怎麼可能,fuck,這完全顛覆了啊…..
主要原因:
當我們在更新UI時,Android中的ViewRootImpl類中的checkThread()方法會檢查當前更新UI所在的線程,如圖
3937 void More ...checkThread() {
//檢查執行更新UI所在的線程
3938 if (mThread != Thread.currentThread()) {
//如果不在UI線程,就會拋出下面的異常,大家應該很眼熟吧
3939 throw new CalledFromWrongThreadException(
3940 "Only the original thread that created a view hierarchy can touch its views.");
3941 }
3942 }
查看系統源碼後,你會發現,ViewRootImpl類會在 Activity的onResume()方法執行完成後才初始化,這也就解釋了上面代碼能運行的原因了,但是,你發現沒有,我們在子線程中沒有做任何的耗時操作,如果我在子線程中添加這句代碼:
SystemClock.sleep(100);
那麼系統將會拋出異常:”Only the original thread that created a view hierarchy can touch its views.”
不能在非UI線程中更新UI.
那麼問題來了,如果ViewRootImpl類沒有初始化完成,那麼view視圖是如何顯示出來的呢???我也正在解決中…….
另外,當我們在子線程中獲取到ViewRoot,我們可以調用addView()方法在子線程中更新UI,這其中的詳情就靠大家去探索了…..
dataBinding與ListView及事件,databinding2015年Google IO大會分布了DataBinding庫,能夠更快捷便利的實現MVVM結構模式
android okvolley框架搭建,androidokvolley最近新出了很多好東西都沒時間去好好看看,現在得好好復習下了,記下筆記 記得以前用的框架是andro
算法—8.有序數組中的二分查找,算法數組二分 1.具體算法 /** * 算法3.2 二分查找(基於有序數組) * Created by huazhou on 201
Android 巧妙實現圖片和文字上下布局或者左右布局,最近去了一家新公司,然後開始做新的項目,看其代碼發現了一個很巧妙的方法來實現圖片在上面文字在下面的布局方式。只需要