Android开发之布局优化

1、抽象布局标签

(1) <include>标签

include标签经常使用于将布局中的公共部分提取出来供其它layout共用,以实现布局模块化。这在布局编写方便提供了大大的便利。

以下以在一个布局main.xml中用include引入还有一个布局foot.xml为例。main.mxl代码例如以下:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent" >

<ListView

android:id="@+id/simple_list_view"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_marginBottom="@dimen/dp_80" />

<include layout="@layout/foot.xml" />

</RelativeLayout>

当中include引入的foot.xml为公用的页面底部,代码例如以下:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<?

xml
version="1.0"
encoding="utf-8"?

>

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"
>

<Button

android:id="@+id/button"

android:layout_width="match_parent"

android:layout_height="@dimen/dp_40"

android:layout_above="@+id/text"/>

<TextView

android:id="@+id/text"

android:layout_width="match_parent"

android:layout_height="@dimen/dp_40"

android:layout_alignParentBottom="true"

android:text="@string/app_name"
/>

</RelativeLayout>

<include>标签唯一须要的属性是layout属性,指定须要包括的布局文件。能够定义android:id和android:layout_*属性来覆盖被引入布局根节点的相应属性值。

注意又一次定义android:id后。子布局的顶结点i就变化了。

(2) <viewstub>标签

viewstub标签同include标签一样能够用来引入一个外部布局。不同的是。viewstub引入的布局默认不会扩张,即既不会占用显示也不会占用位置,从而在解析layout时节省cpu和内存。

viewstub经常使用来引入那些默认不会显示,仅仅在特殊情况下显示的布局,如进度布局、网络失败显示的刷新布局、信息出错出现的提示布局等。

以下以在一个布局main.xml中增加网络错误时的提示页面network_error.xml为例。main.mxl代码例如以下:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

<?

xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent" >

……

<ViewStub

android:id="@+id/network_error_layout"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout="@layout/network_error" />

</RelativeLayout>

当中network_error.xml为仅仅有在网络错误时才须要显示的布局,默认不会被解析,演示样例代码例如以下:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

<?xml
version="1.0"
encoding="utf-8"?

>

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"
>

<Button

android:id="@+id/network_setting"

android:layout_width="@dimen/dp_160"

android:layout_height="wrap_content"

android:layout_centerHorizontal="true"

android:text="@string/network_setting"
/>

<Button

android:id="@+id/network_refresh"

android:layout_width="@dimen/dp_160"

android:layout_height="wrap_content"

android:layout_below="@+id/network_setting"

android:layout_centerHorizontal="true"

android:layout_marginTop="@dimen/dp_10"

android:text="@string/network_refresh"
/>

</RelativeLayout>

在java中通过(ViewStub)findViewById(id)找到ViewStub。通过stub.inflate()展开ViewStub,然后得到子View。例如以下:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

private View networkErrorView;

private void showNetError() {

// not repeated infalte

if (networkErrorView != null) {

networkErrorView.setVisibility(View.VISIBLE);

return;

}

ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);

networkErrorView = stub.inflate();

Button networkSetting = (Button)networkErrorView.findViewById(R.id.network_setting);

Button refresh = (Button)findViewById(R.id.network_refresh);

}

private void showNormal() {

if (networkErrorView != null) {

networkErrorView.setVisibility(View.GONE);

}

}

在上面showNetError()中展开了ViewStub,同一时候我们对networkErrorView进行了保存,这样下次不用继续inflate。

这就是后面第三部分提到的降低不必要的infalte。

viewstub标签大部分属性同include标签相似。

上面展开ViewStub部分代码

Java

1

2

ViewStub
stub
=
(ViewStub)findViewById(R.id.network_error_layout);

networkErrorView
=
stub.inflate();

也能够写成以下的形式

Java

1

2

3

View viewStub = findViewById(R.id.network_error_layout);

viewStub.setVisibility(View.VISIBLE);   // ViewStub被展开后的布局所替换

networkErrorView =  findViewById(R.id.network_error_layout); // 获取展开后的布局

效果一致,仅仅是不用显示的转换为ViewStub。通过viewstub的原理我们能够知道将一个view设置为GONE不会被解析,从而提高layout解析速度。而VISIBLE和INVISIBLE这两个可见性属性会被正常解析。

(3) <merge>标签
在使用了include后可能导致布局嵌套过多。多余不必要的layout节点。从而导致解析变慢,不必要的节点和嵌套可通过hierarchy viewer(以下布局调优工具中有详细介绍)或设置->开发人员选项->显示布局边界查看。

merge标签可用于两种典型情况:
a.  布局顶结点是FrameLayout且不须要设置background或padding等属性,能够用merge取代,由于Activity内容试图的parent view就是个FrameLayout,所以能够用merge消除仅仅剩一个。
b.  某布局作为子布局被其它布局include时,使用merge当作该布局的顶节点,这样在被引入时顶结点会自己主动被忽略。而将其子节点所有合并到主布局中。

以(1) <include>标签的演示样例为例,用hierarchy viewer查看main.xml布局例如以下图:


能够发现多了一层不是必需的RelativeLayout,将foot.xml中RelativeLayout改为merge,例如以下:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<?

xml
version="1.0"
encoding="utf-8"?>

<merge
xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"
>

<Button

android:id="@+id/button"

android:layout_width="match_parent"

android:layout_height="@dimen/dp_40"

android:layout_above="@+id/text"/>

<TextView

android:id="@+id/text"

android:layout_width="match_parent"

android:layout_height="@dimen/dp_40"

android:layout_alignParentBottom="true"

android:text="@string/app_name"
/>

</merge>

执行后再次用hierarchy viewer查看main.xml布局例如以下图:

这样就不会有多余的RelativeLayout节点了。

2、去除不必要的嵌套和View节点

(1) 首次不须要使用的节点设置为GONE或使用viewstub

(2) 使用RelativeLayout取代LinearLayout

大约在Android4.0之前。新建project的默认main.xml中顶节点是LinearLayout,而在之后已经改为RelativeLayout,由于RelativeLayout性能更优,且能够简单实现LinearLayout嵌套才干实现的布局。

4.0及以上Android版本号可通过设置->开发人员选项->显示布局边界打开页面布局显示,看看是否有不必要的节点和嵌套。4.0下面版本号可通过hierarchy viewer查看。

3、降低不必要的infalte

(1) 对于inflate的布局能够直接缓存。用所有变量取代局部变量。避免下次需再次inflate

如上面ViewStub演示样例中的

Java

1

2

3

4

if (networkErrorView != null) {

networkErrorView.setVisibility(View.VISIBLE);

return;

}

(2) ListView提供了item缓存。adapter getView的标准写法。例如以下:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

@Override

public
View
getView(int
position,
View
convertView,
ViewGroup
parent)
{

ViewHolder
holder;

if
(convertView
==
null)
{

convertView
=
inflater.inflate(R.layout.list_item,
null);

holder
=
new
ViewHolder();

……

convertView.setTag(holder);

}
else
{

holder
=
(ViewHolder)convertView.getTag();

}

}

/**

*
ViewHolder

*

*
@author [email protected] 2013-08-01

*/

private
static
class
ViewHolder
{

ImageView
appIcon;

TextView  appName;

TextView  appInfo;

}

关于ListView缓存原理可见Android
ListView缓存机制

4、其它点

(1) 用SurfaceView或TextureView取代普通View

SurfaceView或TextureView能够通过将画图操作移动到还有一个单独线程上提高性能。

普通View的绘制过程都是在主线程(UI线程)中完毕,假设某些画图操作影响性能就不好优化了,这时我们能够考虑使用SurfaceView和TextureView。他们的画图操作发生在UI线程之外的还有一个线程上。

由于SurfaceView在常规视图系统之外。所以无法像常规试图一样移动、缩放或旋转一个SurfaceView。

TextureView是Android4.0引入的,除了与SurfaceView一样在单独线程绘制外。还能够像常规视图一样被改变。

(2) 使用RenderJavascript

RenderScript是Adnroid3.0引进的用来在Android上写高性能代码的一种语言。语法给予C语言的C99标准,他的结构是独立的,所以不须要为不同的CPU或者GPU定制代码代码。

(3) 使用OpenGL画图

Android支持使用OpenGL API的高性能画图,这是Android可用的最高级的画图机制,在游戏类对性能要求较高的应用中得到广泛使用。

Android 4.3最大的改变,就是支持OpenGL ES 3.0。相比2.0。3.0有很多其它的缓冲区对象、添加了新的着色语言、添加多纹理支持等等,将为Android游戏带来更出色的视觉体验。

(4) 尽量为全部分辨率创建资源

降低不必要的硬件缩放。这会降低UI的绘制速度,可借助Android asset studio

5、布局调优工具

(1) hierarchy viewer

hierarchy viewer能够方便的查看Activity的布局,各个View的属性、measure、layout、draw的时间,假设耗时较多会用红色标记。否则显示绿色。

hierarchy viewer.bat位于<sdk>/tools/文件夹下。

使用可见:Using Hierarchy Viewer, 演示样例图例如以下:

(2) layoutopt

layoutopt是一个能够提供layout及其层级优化提示的命令行,在sdk16以后已经被lint代替,在Windows->Show View->Other->Android->Lint Warnings查看lint优化提示

时间: 2024-11-04 17:03:23

Android开发之布局优化的相关文章

android开发中图片优化步骤

android开发中图片优化方法 1.图片加载方法,方便用户加载图片 /*** * 加载本地图片 * @param context:主运行函数实例 * @param bitAdress:图片地址,一般指向R下的drawable目录 * @return */ public final Bitmap CreatImage(Context context, int bitAdress) { Bitmap bitmaptemp = null; bitmaptemp = BitmapFactory.dec

Android开发 UI布局

Android开发 UI布局一.线性布局LinearLayout 什么是线性布局? 其实呢,线性布局就是把所有的孩子摆在同一条线上 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_paren

Android开发-动态布局小记

android动态布局相比静态布局,动态布局不用再将xml转变了布局代码,提高了一定的效率,当然可以忽略不记.动态布局主要是比较灵活,可以很快的在代码中直接修改布局,并直接使用控件进行业务逻辑开发.但代码量通常比较大,维护没有静态布局方便.不过,作为一个android开发人员,掌握一定的动态布局技巧,有时在工作中也是可以提高一定的代码开发效率.   在动态布局中,要想实现一个布局,一般是先创建五大布局的对象.然后对这些对象进行属性设置,之后再向里面添加子布局或控件. 以RelativeLayou

我的Android进阶之旅------&gt;Android中的布局优化 include、merge 、ViewStub

1.如何重用布局文件? 可以使用<include>标签引用其他的布局文件,并用android:id属性覆盖被引用布局文件中顶层节点的android:id属性值.代码如下: <!--引用mylayout.xml--> <include android:id="@+id/layout1" layout="@layout/mylayout"/> 2.减少视图层级<merge /> 无论布局文件的根节点是什么,系统都会在上一层

Android开发,布局xml文件命名注意事项——不能包含任何大写字母

转自:http://blog.sina.com.cn/s/blog_628b45090100zuit.html 在开发Android应用时,会接触到布局文件,一般在 工程名/res/layout/*.xml 目录下,这与网页开发时使用css控制布局类似,主要目的是使布局与程序代码分开,便于布局的修改以及控制. 如果使用eclipse平台开发,每一个Android项目,都会有一个R.java文件,该文件用于标识所有的资源,当资源文件(一般是位于res目录的下的*.xml文件)被修改了,R.java

Android开发之布局文件LinearLayout

LinearLayout-线性布局,该布局中的控件按照水平方向排列或者竖直方向排列. 通过属性android:orientation=""决定的,可选值:vertical和horizontal. 同时有一个比重属性,android:layout_weight="",可以通过填写每个控件的比重,获取控件在布局中的大小. 设计时可以只设定一行或一列的某个控件的比重属性,让其他控件不参与比重,只需要在该控件中设置android:layout_weight="&q

Android 开发中 布局加载的原理

Android 加载的优先级 是怎么样的? 我现在不了解 他是如何加载的额> 我现在 遇到 的问题是 我的app 主要是面向 720 和 480 的手机 但是有一些 320 的手机 安装的时候直接崩溃 你的意思 是 android 内部加载的布局文件的话 Android 加载内部机制: 第一: 加载 指定布局的的 layout 例如 : Layout-hdpi 第二: 如果没有 layout-720 就去加载 layout! 这样就解决了 APP 中的error: java.lang.Unsup

android开发之布局

     目前用得比较多的布局有线性布局.相对布局以及帧布局. 线性布局      特点:组件一个挨着一个排列,通过设置,可以是横向排列或者是纵向排列.   帧布局      特点:一个组件一帧,叠加在一起,起始位置都在布局的左上角,可以通过设置控制组件位置.      如下面的xml文件,定义了6个TextView,每一个TextView都设置在布局的正中间,每一个颜色都不一样,并且越在外层,面积越小,就形成了如下效果.注意,在帧布局中,越后声明的控件在越上层,如果a控件在b控件之前声明,那么

Android开发--微信布局(ListView)基本运用

ListView 1.ListVeiw 用来展示列表的View. 2.适配器 用来把数据映射到ListView上的中介. 3.数据    具体的将被映射的字符串,图片,或者基本组件. 根据列表的适配器类型,列表分为三种,ArrayAdapter,SimpleAdapter和SimpleCursorAdapter 其中以ArrayAdapter最为简单,只能展示一行字.SimpleAdapter有最好的扩充性,可以自定义出各种效果.SimpleCursorAdapter可以认为是SimpleAda