view.post()什么情況下使用
- 通過view.post可以獲取元素的高度和寬度
為什么可以獲取到測(cè)量后的高度
- view.post 在callback的時(shí)候說明是已經(jīng)完成view的measure苍凛,Layout趣席, draw
- 開始我們最喜歡的源碼跟進(jìn)環(huán)節(jié)
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
// 1. 先說結(jié)論,當(dāng)已經(jīng)view已經(jīng)attatch醇蝴,調(diào)用attach的handler宣肚,執(zhí)行post
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
//2. 如果沒有的話,比如我們?cè)趏ncreate方法里調(diào)用view.post悠栓,這個(gè)時(shí)候就是沒有
然后就會(huì)被緩存起來霉涨,知道attach后開始調(diào)用
getRunQueue().post(action);
return true;
}
先從第一種情況說起。 view是何時(shí)attach的,看一下attachInfo是何時(shí)賦值的
void dispatchAttachedToWindow(AttachInfo info){
mAttachInfo = info
// 執(zhí)行所有的[真正開始進(jìn)入隊(duì)列的地方]
if (mRunQueue != null) {
// 在dispatchToWindow的時(shí)候執(zhí)行所有的緩存的task
mRunQueue.executeActions(info.mHandler);
mRunQueue = null;
}
}
繼而繼續(xù)跟進(jìn)View.java##dispatchAttachedToWindow() 何時(shí)調(diào)用的, 首先ViewGroup中肯定會(huì)調(diào)用到闸迷。 果然
ViewGroup.java
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
mGroupFlags |= FLAG_PREVENT_DISPATCH_ATTACHED_TO_WINDOW;
// 先完成自身的dispatch嵌纲,這里對(duì)于ViewTree是按照深度優(yōu)先先序遍歷
super.dispatchAttachedToWindow(info, visibility);
mGroupFlags &= ~FLAG_PREVENT_DISPATCH_ATTACHED_TO_WINDOW;
final int count = mChildrenCount;
final View[] children = mChildren;
for (int i = 0; i < count; i++) {
final View child = children[i];
// 循環(huán)調(diào)用子View的
child.dispatchAttachedToWindow(info,
combineVisibility(visibility, child.getVisibility()));
}
}
接著肯定是在根view DecorView中看有沒調(diào)用,確認(rèn)沒有后腥沽。去管理view的 繪制以及事件的類ViewRootImpl.java中去看看, 果然在這里調(diào)用了逮走。
private void performTraversals(){
// 這里的mView,就是DecorView
final View host = mView;
if(mFirst){
host.dispatchAttachedToWindow(mAttachInfo, 0);
}
// 測(cè)量
performMesaure();
// 布局
performLayout();
// 繪制
performDraw();
}
于是結(jié)合[真正開始進(jìn)入隊(duì)列的地方] 這個(gè)地方今阳,問題就來师溅,這個(gè)明明是在view繪制之前調(diào)用的嘛,這樣不是取值為0嗎盾舌,
這個(gè)地方又要回到之前在“再讀源碼值消息機(jī)制里”里的消息屏障了墓臭。這里所有的繪制消息會(huì)優(yōu)先執(zhí)行,然后再執(zhí)行 post的這個(gè)target