您的位置:首页 > 移动开发 > Android开发

Android 布局优化

2016-02-15 14:46 417 查看
1.减少布局的嵌套,这一点也是最重要的

搞android的都知道,android的整个UI布局文件最后也是要一层一层的解析成View对象的,如果层次太深的话,对导致递归的层次太深而极大的影响解析速度,所以,我们一定不能让布局文件的层次太深,要想做到布局文件的层次不深,通常用到的手段有:1)使用RelativeLayout代替LinearLayout。2)编写完布局文件时,可以使用HieracyView工具检查是否有多余的无用布局,如果有,则一定要去掉无用的布局。最好是10层以下,尽量不要超过15层。

2.布局重用。

一些可以公用的布局我们不必要每次都重写一遍,可以将其写为一个独立的布局文件,最后使用include标签将布局引用即可,然而,严格上来讲,布局重用只是减少了我们代码的编写量,并不能达到对应用的优化作用,而且,在使用include时会很容易产生第一点中的无用父布局

3.使用merge标签去消除include标签所引入的无用布局

顾名思义,就是合并、融合的意思。使用它可以有效的将某些符合条件的多余的层级优化掉。使用merge的场合主要有两处:

(1) 自定义View中使用,父元素尽量是FrameLayout,当然如果父元素是其他布局,而且不是太复杂的情况下也是可以使用的

(2) Activity中的整体布局,根元素需要是FrameLayout

使用Merge注意事项

但是使用merge标签还是有一些限制的,具体有以下几点:

(1)merge只能用在布局XML文件的根元素

(2)使用merge来inflate一个布局时,必须指定一个ViewGroup作为其父元素,并且要设置inflate的attachToRoot参数为true。(参照inflate(int, ViewGroup, boolean))

(3)不能在ViewStub中使用merge标签。最直观的一个原因就是ViewStub的inflate方法中根本没有attachToRoot的设置

还要说一下,因为Window窗体(比如Activity)加载时会自动添加PhoneWindow$DecorView和FrameLayout(id/content)两层布局,所以如果我们在Activity的自定义布局根元素中使用merge,而且想设置总体背景什么的,可以用(id/content)将FrameLayout取出来,再设置属性,可以这样实现:

[code]//setContentView(R.layout.layout_showset);  
       FrameLayout frameLayout = (FrameLayout)this.getWindow().getDecorView().findViewById(android.R.id.content);  
       frameLayout.setBackgroundResource(R.drawable.bg_repeated_main);  
       LayoutInflater.from(this).inflate(R.layout.layout_showset, frameLayout, true);


4.利用 ViewStub延迟加载一些用不到的布局,

这是什么玩应儿呢?其实就是一个轻量级的页面,我们通常使用它来做预加载处理,来改善页面加载速度和提高流畅性,ViewStub本身不会占用层级,它最终会被它指定的层级取代。

在一些场合取代android:visibility=”gone”的用法,因为被gone掉的布局不断是会同时创建对象的。那为什么使用ViewStub就高效呢,

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

setMeasuredDimension(0, 0);

}

@Override

public void draw(Canvas canvas) {

}

由onMeasure()方法和draw()方法可以看出, ViewStub的初始宽高都是零,所以他开始不会占用空间,其次draw()方法也没有执行任何的绘制,由这两个方法就可以看出,ViewStub的确很高效。

在代码中要操纵ViewStub的时候,要首先使用viewstub.inflate()方法,将其所拥有的View初始化进去。否则会报空指针错误。

但ViewStub也不是万能的,下面总结下ViewStub能做的事儿和什么时候该用ViewStub,什么时候该用可见性的控制。

[code] 首先来说说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的可见性来控制。


[code]<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.listviewdemo.MainActivity" >

    <ViewStub
        android:id="@+id/viewstub1"
        android:layout = "@layout/text_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
         />
    <ViewStub
        android:id="@+id/viewstub2"
            android:layout = "@layout/image_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
         />

</LinearLayout>


主页面的布局文件,定义了两个ViewStub,并且分别使用layout属性指定了所要填充的布局。

布局文件我就不给出了,很简单,然后我们在代码中这样使用:

[code]public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         if ((((int) (Math.random() * 100)) & 0x01) == 0) {  
             ViewStub viewStub1 = (ViewStub) findViewById(R.id.viewstub1);
             viewStub1.inflate();
             System.out.println("viewstub1:===="+viewStub1);
             TextView textView = (TextView) findViewById(R.id.textview);
             textView.setText("The tree of liberty must be refreshed from time to time" +  
                    " with the blood of patroits and tyrants! Freedom is nothing but " +  
                    "a chance to be better!");
         }  else{
             ViewStub viewStub2 = (ViewStub) findViewById(R.id.viewstub2);
             viewStub2.inflate();
             ImageView imageView = (ImageView) findViewById(R.id.imageview);
             imageView.setImageResource(R.drawable.ym2);
         }
    }


5.减少不同层间的背景重绘,例如,如果某个view父布局的背景已经设置为了白色,则不需要再为此view设置背景色,通过这个简单的小技巧,可以非常多的提升速度。

6.6.如果整个App都使用了自定义的Title和background,则我们可以使用自定义的style,永久的去掉系统默认为我们的Activity所添加的title和background,也可以提高Activity的渲染速度。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: