再论布局优化

- 去除不必要的嵌套和节点
    这是最基本的一条,但也是最不好做到的一条,往往不注意的时候难免会一些嵌套等。    
- 首次不需要的节点设置为`GONE`或使用`ViewStud`.       
- 使用`Relativelayout`代替`LinearLayout`.        
平时写布局的时候要多注意,写完后可以通过`Hierarchy Viewer`或在手机上通过开发者选项中的显示布局边界来查看是否有不必要的嵌套。

- 使用`include`                
`include`可以用于将布局中一些公共的部分提取出来。在需要的时候使用即可,比喻一些页面统一的`loading`页。                   
`include`标签的`layout`属性指定所要包含的布局文件,我们也可以通过`android:id`或者一些其他的属性来覆盖被引入布局的根节点所对应
 的属性值。      
```xml
<include
layout="@layout/loading"
android:id="@+id/loading_main" />
```
`loading.xml`内容为:    
```xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">


<ProgressBar
android:id="@+id/pb_loadiing"
android:layout_width="28dip"
android:layout_height="28dip"
android:layout_centerInParent="true"
android:indeterminateDrawable="@drawable/progressbar_anim_drawable" />


<TextView
android:layout_below="@id/pb_loadiing"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="loading..."
android:textSize="15sp" />
</RelativeLayout>
```


- 使用`<merge>`标签                      
`merge`可以有效的解决布局的层级关系。我们通过一个例子来说明一下:            
```xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">


<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"


android:scaleType="center"
android:src="@drawable/ic_launcher" />


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dip"
android:textSize="22sp"
android:textColor="#990000"
android:layout_gravity="center_horizontal|bottom"
android:text="TEST" />


</FrameLayout>
```


我们在一个页面中显示该部分内容,运行后观察`Hierarchy Viewer`。                              
我们会发现除了我们布局最外层还会有一层`FrameLayout`,这是因为`Activity`内容视图的`parent view`就是一个`FrameLayout`,所以对于我们来说无意中已经多了一层毫无意义的布局。      
接下来`merge`的功能就能发挥了,修改代码如下。              
```xml
<merge xmlns:android="http://schemas.android.com/apk/res/android">


<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="center"
android:src="@drawable/ic_launcher" />


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dip"
android:textSize="22sp"
android:textColor="#990000"
android:layout_gravity="center_horizontal|bottom"
android:text="TEST" />


</merge>
```
接下来我们在用`Hierarchy Viewer`观察就会发现完美的去掉了一层`FrameLayout`                                
当然上面我们使用`merge`是因为跟布局正好是`FrameLayout`并且没有`backgroud`和`padding`等这些属性。如果根本局是`LinearLayout`等,就没法直接使用`merge`了。
在`include`的时候很容易造成布局层级嵌套过多,结合`merge`使用能有效解决这个问题。

- 使用`ViewStub`                           
    `ViewStub`标签与`include`一样可以用来引入一个外部布局,但是`Viewstub`引入的布局默认不会解析与显示,宽高为0,`View`也为`null`,这样就会在解析`layout`时节省`cpu`和内存。简单的理解就是`ViewStub`是
`include`加上`GONE`.`ViewStub`常用来引入那些默认不会显示,只在特殊情况下显示的布局,如进度布局、网络失败显示的刷新布局、信息出错出现的提示布局等.
    ```xml
<?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_unreachble"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/network_unreachble" />


</RelativeLayout>
```
在代码中通过`(ViewStub)findViewById(id)`找到`ViewStub`,使用`inflate()`展开`ViewStub`,然后得到子`View`,如下:
```java
private View mNetErrorView;


private void showNetError() {
if (mNetErrorView != null) {
mNetErrorView.setVisibility(View.VISIBLE);
return;
}


ViewStub stub = (ViewStub)findViewById(R.id.network_unreachble);
// 解析并且显示该部分,返回值就是解析后的该`View`
mNetErrorView = stub.inflate();
Button networkSetting = (Button)mNetErrorView.findViewById(R.id.bt_network);
}


private void showNormal() {
if (mNetErrorView != null) {
mNetErrorView.setVisibility(View.GONE);
}
}
```
或者也可以通过第二种方式:
```java
View viewStub = findViewById(R.id.network_unreachble);
// ViewStub被展开后的布局所替换
viewStub.setVisibility(View.VISIBLE);   
// 获取展开后的布局
mNetErrorView =  findViewById(R.id.network_unreachble); 
```


- 减少不必要的`Inflate`                

    如上一步中`stub.infalte()`后将该`View`进行记录或者是`ListView`中`item inflate`的时候。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值