当前位置: 首页 > 科技观察

Android使用ViewStub提升布局性能

时间:2023-03-12 10:18:22 科技观察

在Android开发中,View是我们必须要接触到的显示技术。通常,随着View视图变得越来越复杂,整体布局的性能也会下降。这里是一个在某些场景下提升布局性能的view,它就是ViewStub。什么是ViewStub?ViewStub是View的子类。它是不可见的,它的大小为0。它用于延迟加载布局资源注意,关于Stub的解释Stub是一个小程序例程,它替代了一个较长的程序,可能稍后加载或位于远程在Java中,一堆是指用来替换关联代码或未实现代码的代码。ViewStub的使用场景如上图所示。一个ListView包含新闻、商业、科技等item,每个Item包含对应的子主题,但是子主题的View(蓝色区域)只需要在点击展开按钮时加载。如果默认加载子主题的View,会造成内存占用和CPU消耗,所以,这个时候,ViewStub就派上用场了。使用ViewStub可以延迟布局资源的加载。ViewStub的使用方法1.在布局文件中使用ViewStub标签2.展开布局ViewStubmyViewStub=(ViewStub)findViewById(R.id.myViewStub);if(myViewStub!=null){myViewStub.inflate();//或者以下面的形式加载//myViewStub.setVisibility(View.VISIBLE);}关于ViewStub,除了inflate方法,我们还可以调用setVisibility()方法加载布局文件,一旦布局加载完成,ViewStubandroid:id将从当前布局级别中删除。指定的ViewStubID用于查找延迟加载的ViewStubandroid:layout延迟加载布局的资源idandroid:inflatedId加载布局的重写id。文档中有这样的描述注意:ViewStub的一个缺点是目前不支持在layouts中的tag被inflate。这意味着ViewStub不支持标签。关于标签不支持的程度,我们进行简单验证验证1:直接标签如下,我们有一个布局文件,名称为merge_layout.xml替换对应ViewStub的android:layout属性值后,运行后(点击Button按钮),产生如下crashEAndroidRuntime:android.view.InflateException:BinaryXMLfileline#1:只能与validViewGrouproot和attachToRoot=trueEAndroidRuntime:atandroid.view.LayoutInflater.i一起使用nflate(LayoutInflater.java:551)EAndroidRuntime:atandroid.view.LayoutInflater.inflate(LayoutInflater.java:429)EAndroidRuntime:atandroid.view.ViewStub.inflate(ViewStub.java:259)EAndroidRuntime:atcom.droidyue.viewstubsample.MainActivity$1.onClick(MainActivity.java:20)EAndroidRuntime:atandroid.view.View.performClick(View.java:5697)EAndroidRuntime:atandroid.widget.TextView.performClick(TextView.java:10815)EAndroidRuntime:atandroid.view.View$PerformClick.run(View.java:22526)EAndroidRuntime:atandroid.os.Handler.handleCallback(Handler.java:739)EAndroidRuntime:atandroid.os.Handler.dispatchMessage(Handler.java:95)EAndroidRuntime:atandroid.os.Looper.loop(Looper.java:158)EAndroidRuntime:atandroid.app.ActivityThread.main(ActivityThread.java:7237)EAndroidRuntime:atjava.lang.reflect.Method.invoke(NativeMethod)EAndroidRuntime:atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)EAndroidRuntime:atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)EAndroidRuntime:Causedby:android.view.InflateException:canbeusedonlywithvalidViewGrouprootandattachToRoot=trueEAndroidRuntime:atandroid.view.LayoutInflater.inflate(LayoutInflater.java:491)EAndroidRuntime:...13更可见,直接Label,不支持ViewStub。验证第二个间接ViewStub下面的布局是否间接使用了merge标签。文件名为include_merge.xml然后修改ViewStub的android:layout值,运行,一切正常。另外,这个例子也验证了ViewStub也很好地支持标签。一点代码分析一下ViewStubinflatevssetVisibilityinflate和setVisibility有共同点加载布局可以实现/***Whenvisibilityissetto{@link#VISIBLE}or{@link#INVISIBLE},*{@link#inflate()}isinvokedandthisStubbedViewisreplacedinitsparent*bytheinflatedlayoutresource.**@paramvisibilityOneof{@link#VISIBLE}、{@link#INVISIBLE}或{@link#GONE}。**@see#inflate()*/@OverridepublicvoidsetVisibility(intvisibility){if(mInflatedViewRef!=null){Viewview=mInflatedViewRef.get();if(view!=null){view.setVisibility(visibility);}else{thrownewIllegalStateException("setVisibilitycalledonun-referencedview");}}else{super.setVisibility(visibility);if(visibility==VISIBLE||visibility==INVISIBLE){inflate();}}}setVisibility只有在ViewStub第一次延迟初始化时,visibility为non-GONE时,才会调用inflate方法。inflate源码阅读下面的inflate方法实现,我们会更好的理解android:inflatedId的用途。ViewStub在初始化后从视图层级中移除ViewStub的layoutParameters。应用mInflatedViewRef通过弱引用建立ViewStub和加载View之间的连接。finalViewParentviewParent=getParent();if(viewParent!=null&&viewParentrentinstanceofViewGroup){if(mLayoutResource!=0){finalViewGroupparent=(ViewGroup)viewParent;finalLayoutInflaterfactory=LayoutInflater.from(mContext);finalViewview=factory.inflate(mLayoutResource,parent,false);if(mInflatedId!=NO_ID){视图。setId(mInflatedId);}finalintindex=parent.indexOfChild(this);parent.removeViewInLayout(this);finalViewGroup.LayoutParamslayoutParams=getLayoutParams();if(layoutParams!=null){parent.addView(view,index,layoutParams);}else{parent.addView(view,index);}mInflatedViewRef=newWeakReference(view);if(mInflateListener!=null){mInflateListener.onInflate(this,view);}returnview;}else{thrownewIllegalArgumentException("ViewStubmusthaveavalidlayoutResource");}}else{thrownewIllegalStateException("ViewStubmusthaveanon-nullViewGroupviewParent");}}