实践过程
Hello,大家好啊,我是小空,今天带大家了解下动态加载控件ViewStub。
在平时开发中经常会遇到复杂布局,而每一个view都是会占据内存和消耗cpu的(即使再小,累计成多,一般嵌套7级以上就有明显的卡顿了),布局优化就是我们常做的任务之一,甚至是一块心病。所以我们工作中就要留意布局优化的手段,ViewStub就是其中之一。
大家应该听过merge标签,将某个布局文件的根布局写成merge的,然后对应的布局include引用,会默认不会引入merge帮我们减少一层嵌套。而ViewStub也是类似的实现,区别在于include的merge就已经在view的树结构中了,而viewstub默认没在树中,只有代码调用初始化的时候才会进入树中。
就好比我们排队,前者是两人同时排队,后者是一个人排队拿着个占位的牌子帮另一人占位,等合适的时机再将另一个人插入进来,牌子拿开。
实现方式
布局中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方法。
顺便一提:在当下设备性能越来越好的背景下,关于优化的事情放在开发周期后面再说吧。先出产品再迭代。随着经验的积累,正常开发你也会留意性能优化,随手就解决了。
以上就是Android使用ViewStub实现布局优化方法示例的详细内容,更多关于Android ViewStub布局优化的资料请关注脚本之家其它相关文章!