【Android学习】Android性能优化--布局优化(1)

对于Android的布局来说常常提到的有 5个

  • RelativeLayout

  可以自由设置相对已有ID名的元素的相对位置,比较适合使用比较复杂的不是行列规整的布局

  • LinearLayout

  分为纵列和横列,里面的元素都在该纵列或者行列里面,如果用于复杂的画面,则需要生成很多个LinearLayout来描画,开销比较大。

  • TableLayout

  适用于多行多列的布局格式,里面的元素TableRow是LinerLayout的子类

  • FrameLayout

  里面每个元素都是层叠的,适合于切换里面元素用,里面设置位置是没有用的,只有gravity才有效。

  • AbsoluteLayout

  只能通过坐标设置里面每个元素的位置,只是用于绝对位置固定的布局,对于现在大多数各种size的屏幕适应性不好。


setContentView()这个方法被调后,执行下面 将一个xml文件抽象成画面,

  1. 读取资源数据
  2. 解析布局的XML
  3. 展开顶层视图。

   无论是android也好,还是flex等也罢,其实画面的生命周期包括 OnMeasure(测量)和OnLayout(布局)两个步骤的。

  •    测量过程: 从XML根元素开始进行扫描,计算每个父控件的大小,向下层传递自己控件大小 (measure())

                     measure()返回后就是该空间包括子控件的大小已经 全部设置完毕。

  •     布局过程:从XML根元素开始进行扫描,定位每个子视图,将子控件相对于父控件位置设置完毕。(layout())

可见当Layout的层级越多,解析,测量,布局,加载就会越慢,一个页面的生成速度也就越耗时。

所以一般提高Layout的加载速度减少耗时,核心思想就是减少层级关系,尽量少的使用类的实例。

  • 不规则的嵌套页面使用ReletiveLayout,尽量少用LineLayout,可以减少层级
  • 使用ViewStub延迟加载,只有必要的时候才加载
  • <include/>重用标签,类似于C++中的#include
  • 使用<merge/>标签,两个FrameLayout标签叠加  (当父控件是FrameLayout,多个子控件用include标签,并且子控件也是FrameLayout的结构时,可以叠加后, 这样子控件的内容就直接放入了父控件,少了一层。) 
     

第一个RelativeLayout解释不用多说。先来解释一下ViewStub。ViewStub是不可视的(View.INVISIBLE),SIZE大小为0,可以在运行的时候inflate() 或者setVisibility()时再填充布局。但是注意3点:

1)ViewStub是一次性的,所谓一次性就是,当ViewStub的内容用inflate() 或者setVisibility()替换成相应布局后,ViewStub就立即被删除掉了,

     此时再去findViewByID的时候是取不到该ViewStub的取到的是null。所以,ViewStub的这个View在onCreate使用后就不能再用。

2)ViewStub的size是0,如果该模块的布局根节点用RelativeLayout,当ViewStub下面还有控件A,位置设置成需要相对于ViewStub时候,可能就会出现问题。

    因为XML是在setContentView时期解析的,那时候ViewStub还没有大小,控件A取到的位置是0,这个时候用的是系统默认布局,放在了整个根节点的左上。

    解决方法是1)ViewStup和下面控件A用LineLayout.这样不用自己去计算位置比较省力。

                     2)自己根据ViewStub显示后去获取参数,设置控件A的布局(稍微比较繁琐)。

    下面是1)的简单例子。画面一开始中间是不加载的,只有一个按钮,按钮按下就显示ViewStub所指向的布局。一个是TextView,一个是ImageView

    activity_main.xml

<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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" 
    android:id="@+id/rl"
    android:orientation="vertical">

    <Button android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text = "@string/show_Stub"
            android:id="@+id/inflate"
        />
    <ViewStub android:id="@+id/text_stub"
        android:layout_width="fill_parent"
        android:layout_height="100dp"
        android:layout="@layout/text"
        android:inflatedId="@+id/text_view"
        />
    <ViewStub android:id="@+id/image_stub"
              android:layout_width="fill_parent"
        android:layout_height="400dp"
        android:layout="@layout/imageview"
        android:inflatedId="@+id/image_view"/>
    
    <TextView android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text = "@string/show_Stub"
            android:textSize="20dp"
            android:id="@+id/text_afterStub"/>

</LinearLayout>

imageview.xml

<?xml version ="1.0" encoding="utf-8"?>
<ImageView android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/ic_launcher"
xmlns:android="http://schemas.android.com/apk/res/android"/>

text.xml

<TextView 
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="@string/app_name"
xmlns:android="http://schemas.android.com/apk/res/android"/>

MainActivity.java
其中,两个View的切换还是要通过设置对方的View.GONE来实现的。

public class MainActivity extends Activity  implements OnClickListener{
	
	private View textStub;
	private View imageStub;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		textStub = findViewById(R.id.text_stub);
		Button bt = (Button)findViewById(R.id.inflate);
		imageStub =  findViewById(R.id.image_stub);
		bt.setOnClickListener(this);
	}

	private static boolean flag = true;
	
	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		flag = flag == true? false:true;
		if(flag) {
			textStub.setVisibility(View.VISIBLE);
			if(textStub.getParent() == null) {
				textStub = findViewById(R.id.text_view);
			}
			imageStub.setVisibility(View.GONE);			
		} else {
			imageStub.setVisibility(View.VISIBLE);
			if(imageStub.getParent() == null) {
				imageStub.findViewById(R.id.image_view);
			}
			textStub.setVisibility(View.GONE);
		} 

	}

}






你可能感兴趣的:(android,性能优化,布局)