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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

从源代码角度分析ViewStub 疑问与原理

發布時間:2025/3/14 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从源代码角度分析ViewStub 疑问与原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、提出疑問
ViewStub比較簡單。之前文章都提及到《Android 性能優化 三 布局優化ViewStub標簽的使用》。可是在使用過程中有一個疑惑,究竟是ViewStub上設置的參數有效還是在其包含的layout中設置參數有效?假設不明確描寫敘述的問題,能夠看下下面布局偽代碼。

res/layout/main.xml <LinearLayout ><ViewStubandroid:id="@+id/viewstub"android:layout_width="100dip"android:layout_marginTop="100dip"android:layout_height="wrap_content"android:layout="@layout/sub_layout"/></LinearLayout>res/layout/sub_layout.xml <TextViewandroid:layout_width="50dip"android:layout_marginTop="50dip"android:layout_height="wrap_content"android:text="ViewStub中包括的TextVeiw"/>
上面的代碼中width終于效果是100dip還是50dip?marginTop是100dip還是50dip?帶著這個問題一起看下Android 5.0源代碼看看ViewStub原理。


為了便于把ViewStub與其infalte()載入出來的android:layout視圖做個區分,下文中針對前者統一命名“ViewStub視圖”。后者命名“被 載入視圖”,僅為了描寫敘述統一并不一定是專業名稱。
二、分析ViewStub源代碼
讓ViewStub有兩種方式一種是調用ViewStub.inflate() 第二種是設置ViewStub.setVisibility(View.VISIBLE); 事實上第二種方式依舊是調用的infalte方法,能夠看例如以下ViewStub源代碼。 @Override@android.view.RemotableViewMethodpublic void setVisibility(int visibility) {if (mInflatedViewRef != null) {View view = mInflatedViewRef.get();if (view != null) {view.setVisibility(visibility);} else {throw new IllegalStateException("setVisibility called on un-referenced view");}} else {super.setVisibility(visibility);if (visibility == VISIBLE || visibility == INVISIBLE) {inflate();}}}
ViewStub復寫了setVisibility方法,并在當中調用infalte方法。以下來看此方法源代碼

public final class ViewStub extends View {......public View inflate() {final ViewParent viewParent = getParent(); // 1 為什么能夠直接獲取父視圖?// ViewStub的父視圖必須是ViewGroup的子類if (viewParent != null && viewParent instanceof ViewGroup) {if (mLayoutResource != 0) { // ViewStub必須設置android:layout屬性final ViewGroup parent = (ViewGroup) viewParent;final LayoutInflater factory;if (mInflater != null) {factory = mInflater;} else {factory = LayoutInflater.from(mContext);}// 2 inflate被載入視圖 final View view = factory.inflate(mLayoutResource, parent,false);if (mInflatedId != NO_ID) {view.setId(mInflatedId);}// 從父視圖中獲取當前ViewStub在父視圖中的位置final int index = parent.indexOfChild(this);// 當前ViewStub也是個View只不過用來占位。所以先把占位的ViewStub視圖刪除parent.removeViewInLayout(this);// 3 此處獲取的是ViewStub上面設置的參數final ViewGroup.LayoutParams layoutParams = getLayoutParams();if (layoutParams != null) {parent.addView(view, index, layoutParams);} else {parent.addView(view, index);}// 目的是在復寫的setVisibility方法中使用// 由于ViewStub.setVisibility操作的是被載入視圖并不是當前ViewStub視圖mInflatedViewRef = new WeakReference<View>(view);// 調用監聽if (mInflateListener != null) {mInflateListener.onInflate(this, view);}// 返回被載入視圖,假設不須要當前能夠忽略此返回對象return view;} else {throw new IllegalArgumentException("ViewStub must have a valid layoutResource");}} else {throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");}}...... }

以下說下源代碼中列出的幾點。
?1. 為什么能夠直接獲取父視圖?
ViewStub 繼承自View其自身就是一個視圖,其調用getParent()能夠從父類View上入手、
public class View { public final ViewParent getParent() {return mParent;}void assignParent(ViewParent parent) {if (mParent == null) {mParent = parent;} else if (parent == null) {mParent = null;} else {throw new RuntimeException("view " + this + " being added, but"+ " it already has a parent");}} }

從View的源代碼中獲取到,改動mParent參數的僅有assignParent方法且View中并未調用此方法,以下查看下其子類ViewGroup是否有調用。
public class ViewGroup { public void addView(View child, int index, LayoutParams params) {......addViewInner(child, index, params, false);}private void addViewInner(View child, int index, LayoutParams params,boolean preventRequestLayout) {...... // tell our childrenif (preventRequestLayout) {child.assignParent(this);} else {child.mParent = this;}......} }

從上面源代碼能夠看到在addView方法中會調用addViewInner,當中調用child.assignParent(this);,把自己全部子視圖mParent都設置成當前ViewGroup。

從這一點也能夠看出,ViewStub本身是一個View且載入的時候就已經加入到視圖樹中(View Tree)中,僅接著有另外一個問題既然頁面顯示的時候ViewStub已經被加入到界面上。為什么有看不到ViewStub視圖呢?
疑問:為什么ViewStub盡管是懶載入。可是其自身是一個視圖且展示界面就會加入到視圖樹中,為什么看不到ViewStub?
public final class ViewStub extends View {public ViewStub(Context context) {initialize(context);}private void initialize(Context context) {mContext = context;setVisibility(GONE); // 初始化時把自己設置為隱藏setWillNotDraw(true);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(0, 0); // 全部子視圖都設置為寬高為0}@Overridepublic void draw(Canvas canvas) { // 不正確自身與子視圖進行繪制}@Overrideprotected void dispatchDraw(Canvas canvas) {} }

從以上源代碼能夠看出ViewStub用盡全部辦法讓自己加入到視圖樹上是不顯示ViewStub自身。



2. inflate被載入視圖 再來看下載入android:layout視圖的源代碼。 final View view = factory.inflate(mLayoutResource, parent,?false); 能夠看到通過infalte方法記載的。其三個參數(int resource, ViewGroup root, boolean attachToRoot),各自是: mLayoutResource :?設置的android:layout的值 parent : 通過getParent()獲取即ViewStub的父視圖 false :?attachToRoot設置為false說明忽略androd:layout中根節點的layoutParams參數,即width=50dip與margin50dip
3. 視圖加入ViewStub.getLayoutParams參數 此處源代碼的是獲取ViewStub.getLayoutParams參數設置到anroid:layout載入的視圖上。?即width=100dip與marginTop=100dip生效。

三、總結 開頭的疑問的答案。inflate出來的視圖width=100dip與marginTop=100dip而android:layout視圖中設置的width50dip和marginTop=50dip失效,等于沒有設置。
ViewStub的原理簡單描寫敘述是 1. ViewStub本身是一個視圖。會被加入到界面上,之所以看不到是由于其源代碼設置為隱藏與不繪制。 2. 當調用infalte或者ViewStub.setVisibility(View.VISIBLE);時(兩個都使用infalte方法邏輯),先從父視圖上把當前ViewStub刪除。再把載入的android:layotu視圖加入上 3. 把ViewStub?layoutParams?加入到載入的android:layotu視圖上。而其根節點layoutParams?設置無效。 4. ViewStub是指用來占位的視圖,通過刪除自己并加入android:layout視圖達到懶載入效果



轉載于:https://www.cnblogs.com/bhlsheji/p/5174505.html

總結

以上是生活随笔為你收集整理的从源代码角度分析ViewStub 疑问与原理的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 精品一区二区三区四区视频 | 久久影音 | 国产色秀| 91福利片 | www四虎影院| 丰满少妇高潮久久三区 | 无人在线观看高清视频 | 国产精品久久久久久久av | 日本欧美色图 | av午夜精品 | 91视频最新| 亚洲欧美日韩电影 | 黑人巨大xxxxx性猛交 | 欧美久操 | aaa一级黄色片 | 一区二区精品视频在线观看 | 狠狠看 | 日日麻批 | 中文字幕乱码亚洲精品一区 | 9久久9毛片又大又硬又粗 | 亚洲社区一区二区 | 国产区精品在线 | 亚洲男性天堂 | 哪里可以看毛片 | 名校风暴在线观看免费高清完整 | 中文字幕不卡一区 | 欧美影视| 久久日av| 污的网站 | 黑料视频在线 | 日本一级淫片色费放 | 欧美黄视频在线观看 | jizz久久| 色人阁网站 | videos麻豆| 亚洲av无码成人精品国产 | 国产精品视频区 | 国产午夜性春猛交ⅹxxx | 国产麻豆一精品一av一免费 | 日本精品视频一区二区 | 91大神网址 | 黄色片网站免费在线观看 | 怡红院av亚洲一区二区三区h | 国产探花在线观看 | 在线免费观看国产精品 | 久久久久久不卡 | 黄色高清在线观看 | 超污视频网站 | 久久久久久av无码免费网站下载 | 日本精品一区二区三区在线观看 | 成人毛片在线精品国产 | 蜜桃视频在线网站 | 在线观看中文字幕亚洲 | 夜夜骑夜夜操 | 99爱视频在线 | 国产天堂第一区 | 日日干日日插 | 日韩激情第一页 | 想要xx在线观看 | 成人免费av | 久久一线 | 久久亚洲精少妇毛片午夜无码 | 久久婷婷综合色 | 成人免费版 | 欧美久久久久 | 精品成人久久 | 女人特黄大aaaaaa大片 | 污污网站在线播放 | 91精品视频一区 | 日本精品一二区 | 五月婷婷六月综合 | 国产电影一区二区三区爱妃记 | 国毛片 | 国产美女无遮挡免费 | 天堂中文网在线 | 欧美在线91 | 91免费视频入口 | 天堂久久精品忘忧草 | 国产在线观看网站 | 麻豆传谋在线观看免费mv | 亚洲成人高清在线观看 | 女人十八毛片嫩草av | 一呦二呦三呦精品网站 | 午夜美女网站 | 黄色一级大片在线观看 | 亚洲国产成人精品激情在线 | 综合在线播放 | 欧美高清一级 | 九九热九九热 | 伊人草草| 日日摸日日碰夜夜爽无码 | 欧美熟妇7777一区二区 | 亚洲在线综合 | 销魂奶水汁系列小说 | 欧美八区 | 国产精品伦理 | 国产精品久久伊人 | 久久mm | 午夜影院a |