Android 性能优化
jopen
11年前
一. 通过inflate在Activity中布局是个有性能消耗的过程。每增加一个嵌套的布局和视图都会对应用的性能造成很大的影响。
总之,好的实践是尽量保持布局尽可能简单,尤其是要避免嵌套inflate操作整个新的布局,这是为更新已经存在布局的小变化。
以下几点是包含在Android最佳实践指导原则里的,当然并不绝对:
避免不必要的嵌套:不要把一个布局放置在其他布局里,除非是必要的。
避免使用太多视图:在一个布局中每增加一个新的视图,都会在inflate操作时耗时和消耗资源。任何时候都不要在一个布局中包含超过80个视图,否则,消耗在inflate操作上的时间会很大。
避免深度嵌套:布局可以任意嵌套,这极易于创建复杂和深度嵌套的布局层次。如果没有硬性限制,将嵌套限制在10层以下是好的实践。
优化布局层次,比如减少没效率的或者不必要的嵌套布局,是十分重要的。
Android SDK包含了layoutopt,一个命令行工具,来辅助这个优化工作。运行该命令,参数是布局文件或者布局文件的目录,将分析并给出改善的建议。
二.Android布局优化:
1、优化布局层次结构
避免布局嵌套,此外几个嵌套的LinearLayout实例使用layout_weight参数会导致两次测量,特别是重复的添加,比如ListView、GridView。避免layout_weight
1)、检查你的布局
通过tools/hierarchyviewer.bat找到布局性能瓶颈。
2)、使用Lint检查(几个例子)
LinearLayout保护一个imageview和textView可以使用一个控件来实现。 textView属性android:drawableLeft="@drawable/up“
如根标签仅作为跟布局(无背景等),使用<merge>替代。在代码中inflate一个以merge为根元素的布局文件时候,你需要指定一个ViewGroup 作为其容器,并且要设置attachToRoot 为true
删除没子控件、没背景的布局
如果一个layout只有子控件,没有兄弟控件,并且不是一个ScrollView或者根节点,而且没有设置背景,那么我们可以移除这个父控件,直接把子控件提升为父控件。
尽量减少内嵌的层级,考虑使用更多平级的组件 RelativeLayout or GridLayout来提升布局性能,默认最大的深度是10
2、复用布局<include/>
创建可重用的layout组件
使用定义的组件<includelayout="@layout/titlebar"/>
<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width=”match_parent”
android:layout_height="wrap_content"
android:background="@color/titlebar_bg">
<ImageViewandroid:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/gafricalogo" />
</FrameLayout>
<include android:id=”@+id/news_title”android:layout_width=”match_parent” android:layout_height=”match_parent”layout=”@layout/title”/>
三、动态加载视图
有时候我们需要复杂的视图且少用,我们可以按需要的时候装载以便减少内存,提高体验。原来我们都是设置在布局中,然后使用View.GONE属性,但是好资源影响性能。ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件
定义ViewStub
<ViewStubandroid:id="@+id/stub_import" android:inflatedId="@+id/panel_import"android:layout="@layout/progress_overlay"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_gravity="bottom" />
三. Android布局优化几个重要标签的使用include、merge、ViewStub、requestFocus
include:用于布局的复用
merge:削减布局层级来实现尽量扁平化,仅可作为根节点,多与include结合使用
requestFocus:设置获取焦点的view
ViewStub:不占用任何内存,通过inflate()来加载内部的views
注:
<merge>也有一些使用限制: 只能用于xml layout文件的根元素;在代码中使用LayoutInflater.Inflater()一个以merge为根元素的布局文件时候,需要使用View inflate (int resource, ViewGroup root, boolean attachToRoot)指定一个ViewGroup 作为其容器,并且要设置attachToRoot 为true。