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

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

2014-07-26 22:50 489 查看
对于Android的布局来说常常提到的有 5个

RelativeLayout

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

LinearLayout

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

TableLayout

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

FrameLayout

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

AbsoluteLayout

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

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

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

无论是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);
}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: