網站首頁 編程語言 正文
??實踐過程
Hello,大家好啊,我是小空,今天帶大家了解下動態加載控件ViewStub。
在平時開發中經常會遇到復雜布局,而每一個view都是會占據內存和消耗cpu的(即使再小,累計成多,一般嵌套7級以上就有明顯的卡頓了),布局優化就是我們常做的任務之一,甚至是一塊心病。所以我們工作中就要留意布局優化的手段,ViewStub就是其中之一。
大家應該聽過merge標簽,將某個布局文件的根布局寫成merge的,然后對應的布局include引用,會默認不會引入merge幫我們減少一層嵌套。而ViewStub也是類似的實現,區別在于include的merge就已經在view的樹結構中了,而viewstub默認沒在樹中,只有代碼調用初始化的時候才會進入樹中。
就好比我們排隊,前者是兩人同時排隊,后者是一個人排隊拿著個占位的牌子幫另一人占位,等合適的時機再將另一個人插入進來,牌子拿開。
??實現方式
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/idBtnInflate" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="inflate" /> <ViewStub android:id="@+id/viewStubName" android:inflatedId="@+id/inflatedLayoutName" android:layout="@layout/yourLayout" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
布局中ViewStub其實就是個寬高全是0的View,它默認是不可見的(不是GONE或INVISIBLE的不可見,而是根本沒在view的樹結構里),然后通過調用setVisibility函數或者Inflate函數會將我們的目標布局給加載出來,這樣就實現了延遲加載的效果。
idBtnInflate.setOnClickListener{
viewStubName. inflate()
//或者是下面的形式加載,因為里面會執行inflate
// viewStubName.visibility=View.VISIBLE
}
??知識點
注意,viewstub執行inflate函數后,在當前頁面activity未銷毀之前無法進行第二次inflate。
為什么第二次inflate的時候會報錯呢?仔細看上面列舉的排隊比喻,viewstud就是占位的那個牌子,當你引入的layout插進去后就會移除viewstub控件。那么下次你再進行inflate的時候自然就是報錯了。
為什么大小為0且不繪制? 我們找到ViewStub的源碼:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(0, 0);
}
@Override
public void draw(Canvas canvas) {
}
@Override
protected void dispatchDraw(Canvas canvas) {
}
public void setWillNotDraw(boolean willNotDraw) {
setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
}
重寫draw和dispatchDraw,但卻什么也不寫,再接著onMeasure中進行setMeasuredDimension(0,0);就實現了寬高為0.
而不繪制是將view的Flags設置為了WILL_NOT_DRAW,這個值的作用是view不會進行onDraw方法。
順便一提:在當下設備性能越來越好的背景下,關于優化的事情放在開發周期后面再說吧。先出產品再迭代。隨著經驗的積累,正常開發你也會留意性能優化,隨手就解決了。
原文鏈接:https://juejin.cn/post/7135462014796709925
相關推薦
- 2022-10-04 Go語言底層原理互斥鎖的實現原理_Golang
- 2022-04-06 詳解VS2019使用scanf()函數報錯的解決方法_C 語言
- 2022-10-03 C語言實現經典排序算法的示例代碼_C 語言
- 2022-06-27 Android中的TimePickerView(時間選擇器)的用法詳解_Android
- 2022-04-17 Bootstrap typeahead自動補全插件的坑
- 2023-01-27 C#實現拆分合并Word表格中的單元格_C#教程
- 2022-08-03 使用Apache?Camel表達REST服務的方法_Linux
- 2022-10-27 React的createElement和render手寫實現示例_React
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支