安卓布局优化详解
安卓的布局优化方式目前有三种:使用<Include>标签、使用<ViewStub>标签、使用<merge />
★布局重用<include>标签:
1)使用include标签进行布局复用,这种方式在我实际开发中是用处最普遍的。
2)使用<include />标签可以使用单独的layout属性,这个也是必须用的,我觉得使用起来非常方便。
上个小图:
★需要时使用<ViewStub />
在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局。那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为View.GONE,然后在代码中动态的更改它的可见性。这样的做法的优点是逻辑简单而且控制起来比较灵活。但是它的缺点就是,耗费资源。虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性。也就是说,会耗费内存等资源。
推荐的做法是使用Android.view.ViewStub,ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。这样,就可以使用ViewStub来方便的在运行时,要还是不要显示某个布局。
但ViewStub也不是万能的,下面总结下ViewStub能做的事儿和什么时候该用ViewStub,什么时候该用可见性的控制。
首先来说说ViewStub的一些特点:
1. ViewStub只能Inflate一次,之后ViewStub对象会被置为空。按句话说,某个被ViewStub指定的布局被Inflate后,就不会够再通过ViewStub来控制它了。
2. ViewStub只能用来Inflate一个布局文件,而不是某个具体的View,当然也可以把View写在某个布局文件中。
基于以上的特点,那么可以考虑使用ViewStub的情况有:
1. 在程序的运行期间,某个布局在Inflate后,就不会有变化,除非重新启动。
因为ViewStub只能Inflate一次,之后会被置空,所以无法指望后面接着使用ViewStub来控制布局。所以当需要在运行时不止一次的显示和隐藏某个布局,那么ViewStub是做不到的。这时就只能使用View的可见性来控制了。
2. 想要控制显示与隐藏的是一个布局文件,而非某个View。
因为设置给ViewStub的只能是某个布局文件的Id,所以无法让它来控制某个View。
所以,如果想要控制某个View(如Button或TextView)的显示与隐藏,或者想要在运行时不断的显示与隐藏某个布局或View,只能使用View的可见性来控制。
下面看代码:
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout 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:orientation= "vertical" tools:context= "com.example.nanchen.layoutdemo.MainActivity" > <include android:layout_height= "wrap_content" android:layout_width= "wrap_content" layout= "@layout/menu_layout" /> <ViewStub android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_marginLeft= "20dip" android:layout_marginRight= "20dip" android:layout_marginTop= "10dip" android:id= "@+id/viewstub_demo_text" android:layout= "@layout/viewstub_demo_text_layout" /> <ViewStub android:id= "@+id/viewstub_demo_image" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_marginLeft= "5dip" android:layout_marginRight= "5dip" android:layout= "@layout/viewstub_demo_image_layout" /> </LinearLayout> |
viewstub_demo_image_layout
1 2 3 4 5 6 7 8 9 10 11 12 | <?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" > <ImageView android:id= "@+id/viewstub_demo_imageview" android:layout_width= "wrap_content" android:layout_height= "wrap_content" /> </LinearLayout> |
viewstub_demo_text_layout
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?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" > <TextView android:id= "@+id/viewstub_demo_textview" android:layout_width= "match_parent" android:layout_height= "wrap_content" android:background= "#aa664411" android:textSize= "16sp" /> </LinearLayout> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | package com.example.nanchen.layoutdemo; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.ViewStub; import android.widget.ImageView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); // ViewStub stub = (ViewStub) findViewById(R.id.viewstub_demo_text); // stub.inflate(); // TextView text = (TextView) findViewById(R.id.viewstub_demo_textview); // text.setText("布局优化之ViewStub标签"); ViewStub stub = (ViewStub) findViewById(R.id.viewstub_demo_image); stub.inflate(); ImageView image = (ImageView) findViewById(R.id.viewstub_demo_imageview); image.setImageResource(R.mipmap.ic_launcher); } } |
运行图:
使用的时候的注意事项:
1、某些布局属性要加在ViewStub而不是实际的布局上面,才会起作用,比如上面用的android:layout_margin*系列属性,如果加在TextView上面,则不会起作用,需要放在它的ViewStub上面才会起作用。而ViewStub的属性在inflate()后会都传给相应的布局。
2、 VIewStub中不能嵌套merge标签。
3、 ViewStub只能用来Inflate一个布局文件,而不是某个具体的View,当然也可以把View写在某个布局文件中。如果想操作一个具体的view,还是使用visibility属性吧。
★对于减少视图层次<merge />标签我了解较少,待以后清楚些了再来诉说。
作 者:
南 尘
出 处: http://www.cnblogs.com/liushilin/
关于作者:专注于移动前端的项目开发。如有问题或建议,请多多赐教!欢迎加入Android交流群:118116509
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信我
声援博主:如果您觉得文章对您有帮助,可以点击文章下部【推荐】或侧边【关注】。您的鼓励是作者坚持原创和持续写作的最大动力!
欢迎关注我的公众号,精讲面试、算法、Andrid、Java、Python,旨在打造全网最比心的公众号。

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述