Android中使用ViewStub实现布局优化

Android中使用ViewStub实现布局优化,第1张

概述在Android开发中,View是我们必须要接触的用来展示的技术.通常情况下随着View视图的越来越复杂,整体布局的性能也会随之下降.这里介绍一个在某些场景下提升布局性能的View,它就是ViewStub.

在AndroID开发中,VIEw是我们必须要接触的用来展示的技术.通常情况下随着VIEw视图的越来越复杂,整体布局的性能也会随之下降.这里介绍一个在某些场景下提升布局性能的VIEw,它就是VIEwStub.

VIEwStub是什么

VIEwStub是VIEw的子类 它不可见,大小为0 用来延迟加载布局资源

注,关于Stub的解释

A stub is a small program routine that substitutes for a longer program,possibly to be loaded later or that is located remotely

在Java中,桩是指用来代替关联代码或者未实现代码的代码.

VIEwStub使用场景

 

如上图所示,

一个ListVIEw包含了诸如 新闻,商业,科技 等Item 每个Item又包含了各自对应的子话题, 但是子话题的VIEw(蓝色区域)只有在点击展开按钮才真正需要加载. 如果默认加载子话题的VIEw,则会造成内存的占用和cpu的消耗

所以,这时候就VIEwStub就派上用处了.使用VIEwStub可以延迟加载布局资源.

VIEwStub 怎么用

在布局文件中使用VIEwStub标签

<?xml version="1.0" enCoding="utf-8"?><relativeLayout  xmlns:androID="http://schemas.androID.com/apk/res/androID"  xmlns:tools="http://schemas.androID.com/tools"  androID:layout_wIDth="match_parent"  androID:layout_height="match_parent"  androID:paddingleft="@dimen/activity_horizontal_margin"  androID:paddingRight="@dimen/activity_horizontal_margin"  androID:paddingtop="@dimen/activity_vertical_margin"  androID:paddingBottom="@dimen/activity_vertical_margin"  tools:context="com.droIDyue.vIEwstubsample.MainActivity"> <button   androID:ID="@+ID/clickMe"   androID:text="Hello World!"   androID:layout_wIDth="wrap_content"   androID:layout_height="wrap_content"/>  <VIEwStub   androID:ID="@+ID/myVIEwStub"   androID:inflatedID="@+ID/myInflatedVIEwID"   androID:layout="@layout/include_merge"   androID:layout_wIDth="wrap_content"   androID:layout_height="wrap_content"   androID:layout_below="@ID/clickMe" /></relativeLayout>

2.在代码中inflate布局

VIEwStub myVIEwStub = (VIEwStub)findVIEwByID(R.ID.myVIEwStub);if (myVIEwStub != null) { myVIEwStub.inflate(); //或者是下面的形式加载 //myVIEwStub.setVisibility(VIEw.VISIBLE);}

关于VIEwStub的事

除了 inflate 方法外,我们还可以调用 setVisibility() 方法加载布局文件
一旦加载布局完成后,VIEwStub会从当前布局层级中删除
androID:ID 指定VIEwStub ID,用于查找VIEwStub进行延迟加载
androID:layout 延迟加载布局的资源ID
androID:inflatedID 加载的布局被重写的ID,这里为relativeLayout的ID

VIEwStub的不足

官方的文档中有这样一段描述

Note: One drawback of VIEwStub is that it doesn't currently support the tag in the layouts to be inflated.

意思是VIEwStub不支持 <merge> 标签.

关于不支持 <merge> 标签的程度,我们进行一个简单的验证

验证一:直接 标签

如下,我们有布局文件名为 merge_layout.xml

<merge xmlns:androID="http://schemas.androID.com/apk/res/androID"> <button   androID:layout_wIDth="fill_parent"   androID:layout_height="wrap_content"   androID:text="Yes"/> <button   androID:layout_wIDth="fill_parent"   androID:layout_height="wrap_content"   androID:text="No"/></merge>

替换对应的VIEwStub的androID:layout属性值之后,运行后(点击button按钮)得到产生了如下的崩溃

 E AndroIDRuntime: androID.vIEw.InflateException: Binary XML file line #1: <merge /> can be used only with a valID VIEwGroup root and attachToRoot=true
 E AndroIDRuntime:         at androID.vIEw.LayoutInflater.inflate(LayoutInflater.java:551)
 E AndroIDRuntime:         at androID.vIEw.LayoutInflater.inflate(LayoutInflater.java:429)
 E AndroIDRuntime:         at androID.vIEw.VIEwStub.inflate(VIEwStub.java:259)
 E AndroIDRuntime:         at com.droIDyue.vIEwstubsample.MainActivity$1.onClick(MainActivity.java:20)
 E AndroIDRuntime:         at androID.vIEw.VIEw.performClick(VIEw.java:5697)
 E AndroIDRuntime:         at androID.Widget.TextVIEw.performClick(TextVIEw.java:10815)
 E AndroIDRuntime:         at androID.vIEw.VIEw$PerformClick.run(VIEw.java:22526)
 E AndroIDRuntime:         at androID.os.Handler.handleCallback(Handler.java:739)
 E AndroIDRuntime:         at androID.os.Handler.dispatchMessage(Handler.java:95)
 E AndroIDRuntime:         at androID.os.Looper.loop(Looper.java:158)
 E AndroIDRuntime:         at androID.app.ActivityThread.main(ActivityThread.java:7237)
 E AndroIDRuntime:         at java.lang.reflect.Method.invoke(Native Method)
 E AndroIDRuntime:         at com.androID.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
 E AndroIDRuntime:         at com.androID.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
 E AndroIDRuntime: Caused by: androID.vIEw.InflateException: <merge /> can be used only with a valID VIEwGroup root and attachToRoot=true
 E AndroIDRuntime:         at androID.vIEw.LayoutInflater.inflate(LayoutInflater.java:491)
 E AndroIDRuntime:         ... 13 more

可见,直接的 <merge> 标签,VIEwStub是不支持的.

验证二 间接的VIEwStub

下面布局间接使用了merge标签.文件名为 include_merge.xml

<?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">  <include layout="@layout/merge_layout"/></linearLayout>

然后修改VIEwStub的 androID:layout 值,运行,一切正常.

除此之外,本例也验证了VIEwStub也是对 <include> 标签支持良好的.

关于VIEwStub的一点代码剖析

inflate vs setVisibility

inflate和setVisibility的共同点是都可以实现加载布局

/**  * When visibility is set to {@link #VISIBLE} or {@link #INVISIBLE},* {@link #inflate()} is invoked and this StubbedVIEw is replaced in its parent  * by the inflated layout resource.  *  * @param visibility One of {@link #VISIBLE},{@link #INVISIBLE},or {@link #GONE}.  *  * @see #inflate()   */ @OverrIDe public 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();   }  } }

setVisibility只是在VIEwStub第一次延迟初始化时,并且visibility是非 GONE 时,调用了 inflate 方法.

inflate源码

通过阅读下面的inflate方法实现,我们将更加理解

androID:inflatedID的用途 VIEwStub在初始化后从视图层级中移除 VIEwStub的layoutParameters应用 mInflatedVIEwRef通过弱引用形式,建立VIEwStub与加载的VIEw的联系.
/**  * Inflates the layout resource IDentifIEd by {@link #getLayoutResource()}  * and replaces this StubbedVIEw in its parent by the inflated layout resource.  *  * @return The inflated layout resource.  *  */ public VIEw inflate() {  final VIEwParent vIEwParent = getParent();  if (vIEwParent != null && vIEwParent instanceof VIEwGroup) {   if (mLayoutResource != 0) {    final VIEwGroup parent = (VIEwGroup) vIEwParent;    final LayoutInflater factory = LayoutInflater.from(mContext);    final VIEw vIEw = factory.inflate(mLayoutResource,parent,false);    if (mInflatedID != NO_ID) {     vIEw.setID(mInflatedID);    }    final int index = parent.indexOfChild(this);    parent.removeVIEwInLayout(this);    final VIEwGroup.LayoutParams layoutParams = getLayoutParams();    if (layoutParams != null) {     parent.addVIEw(vIEw,index,layoutParams);    } else {     parent.addVIEw(vIEw,index);    }    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");  } }

关于VIEwStub的研究就是这些,希望对大家关于优化视图有所帮助和启发.

总结

以上是内存溢出为你收集整理的Android中使用ViewStub实现布局优化全部内容,希望文章能够帮你解决Android中使用ViewStub实现布局优化所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1148123.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存