少一些套路,多一些升华

少一点套路,多一点真诚,哈哈,此处套路我们取用一个套路,少一些嵌套和歪路,多一些真诚的优化!!优化布局是Android中很重要的,无论是在自定义控件中,还是在简单的书写布局时,都应该尽量遵循一些优化原则,这样布局的绘制效率才会更高,体验才能更好,本文主要跟大家介绍一下我们开发中常用的几种优化方式:


一、优化布局的层级,Android在绘制界面的时候会消耗性能,如果嵌套过多甚至会影响用户体验,所以我们要尽量优化布局的层级

1、减少布局的嵌套和View节点

(1) 首次不需要使用的节点设置为GONE或使用viewstub

(2)使用RelativeLayout代替LinearLayout,大约在Android4.0之前,新建工程的默认main.xml中顶节点是LinearLayout,而在之后已经改为RelativeLayout,因为RelativeLayout性能更优,且可以简单实现LinearLayout嵌套才能实现的布局。嵌套的 LinearLayout 可能会使得 View 的层级结构很深。使用LinearLayout时,通常我们喜欢用嵌套的布局来动态设置一个View的Visibility ,由于LinearLayout是线性的,因此即使隐藏一个View也不会影响到其它View的排列。而在RelativeLayout中,View的位 置都是相对于其它View的,因此,隐藏之后,会导致之前的View没有参考对象了,导致的相对位置改变,这时你可以使用 alignWithParentIfMissing=”true”来处理这种情况。此外,嵌套使用了 layout_weight 参数的 LinearLayout 的计算量会尤其大,因为每个子元素都需要被测量两次。这对需要多次重复 inflate 的 Layout 尤其需要注意,比如使用 ListView 或 GridView 时。


2、使用抽象布局标签(include, viewstub, merge)

(1) <include>标签

include标签常用于将布局中的公共部分提取出来供其他layout共用,以实现布局模块化,这在布局编写方便提供了大大的便利,<include>标签唯一需要的属性是layout属性,指定需要包含的布局文件。代码示例如下:

<?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" >

    <TextView

        android:id="@+id/simple_textView"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:layout_marginBottom="@dimen/dp_40" />

    <include layout="@layout/footer.xml" />

</RelativeLayout>

footer.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" >

    <Button

        android:id="@+id/btn_sure"

        android:layout_width="match_parent"

        android:layout_height="@dimen/dp_40"

        android:layout_above="@+id/btn_cancel"/>

    <Button

        android:id="@+id/btn_cancel"

        android:layout_width="match_parent"

        android:layout_height="@dimen/dp_40"

        android:layout_alignParentBottom="true"

        android:text="@string/app_name" />

</RelativeLayout>


(2) <viewstub>标签

ViewStub 是一个轻量的视图,不需要大小信息,也不会在被加入的 Layout 中绘制任何东西。每个 ViewStub 只需要设置 android:layout 属性来指定需要被 inflate 的 Layout 类型。viewstub常用来引入那些默认不会显示,只在特殊情况下显示的布局,如进度布局、网络失败显示的刷新布局、信息出错出现的提示布局等。下面我们举一个信息出错的例子,来讲解一下

我们首先定义一个message_error.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/message_error_layout"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:layout="@layout/message_error" />

</RelativeLayout>

message_error.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" >

 

    <TextView

        android:id="@+id/message_error_textView"

        android:layout_width="@dimen/dp_160"

        android:layout_height="wrap_content"

        android:layout_centerHorizontal="true"/>

</RelativeLayout>

通过(ViewStub)findViewById(id)找到ViewStub,通过stub.inflate()展开ViewStub,然后得到子View,如下:

private View msg_error;

 

private void showMsgError() {

// not repeated infalte

if (msg_error!= null) {

msg_error.setVisibility(View.VISIBLE);

return;

}

 

ViewStub stub = (ViewStub)findViewById(R.id.message_error_layout);

msg_error= stub.inflate();

TextView refresh = (Button)

msg_error.findViewById(R.id.message_error_textView);

}

 

private void showNormal() {

if (msg_error!= null) {

msg_error.setVisibility(View.GONE);

}

}

在上面showNetError()中展开了ViewStub,同时我们对networkErrorView进行了保存,这样下次不用继续inflate。这就是后面第三部分提到的减少不必要的infalte。


(3) <merge>标签

在使用了include后可能导致布局嵌套过多,出现不必要的layout节点,从而导致解析变慢。

merge标签可用于两种典型情况:

布局顶结点是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity内容试图的parent view就是个FrameLayout,所以可以用merge消除只剩一个。

    - 

某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,这样在被引入时顶结点会自动被忽略,而将其子节点全部合并到主布局中。

比如,如果你有一个 Layout 是一个竖直方向的 LinearLayout,其中包含两个连续的 View 可以在别的 Layout 中重用,那么你会做一个 LinearLayout 来包含这两个 View ,以便重用。不过,当使用另一个 LinearLayout 来嵌套这个可重用的 LinearLayout 时,这种嵌套 LinearLayout 的方式除了减慢你的 UI 性能外没有任何意义。

为了避免这种情况,你可以用 元素来替代可重用 Layout 的根节点。例如:

<?xml version="1.0" encoding="utf-8"?>

<merge xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent" >

 

    <Button

        android:id="@+id/btn_sure"

        android:layout_width="match_parent"

        android:layout_height="@dimen/dp_40"

        android:layout_above="@+id/btn_cancel"/>

 

    <Button

        android:id="@+id/btn_cancel"

        android:layout_width="match_parent"

        android:layout_height="@dimen/dp_40"

        android:layout_alignParentBottom="true"

        android:text="@string/app_name" />

 

</merge >

现在,当你要将这个 Layout 包含到另一个 Layout 中时(并且使用了 标签),系统会直接把两个 Button 放到 Layout 中,而不会有多余的 Layout 被嵌套。



二、 ListView的优化

(1)如果你有一个包含复杂或者每个项 (item) 包含很多数据的 ListView ,那么上下滚动的性能可能会降低。本节给你一些关于如何把滚动变得更流畅的提示。保持程序流畅的关键,是让主线程(UI 线程)不要进行大量运算。你要确保在其他线程执行磁盘读写、网络读写或是 SQL 操作等。为了测试你的应用的状态,你可以启用 StrictMode。



(2)在 View Holder 中填入视图对象

使用convertView、你的代码可能在 ListView 滑动时经常使用 findViewById(),这样会降低性能。即使是 Adapter 返回一个用于回收的 convertView,你仍然需要查找这个元素并更新它。避免频繁调用 findViewById() 的方法之一,就是使用 View Holder(视图占位符)设计模式。

ViewHolder 存储了标签下的每个视图。这样你不用频繁查找这个元素:

static class ViewHolder { 

TextView text; 

TextView timestamp;

 ImageView icon;

 ProgressBar progress;

 int position;

}

然后,在 Layout 的类中生成一个 ViewHolder 对象:

ViewHolder holder = new ViewHolder();

holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);

...

convertView.setTag(holder);

这样你就可以轻松获取每个视图,而不是用 findViewById() 来不断查找视图,节省了宝贵的运算时间。




主要就这么多了,一般我们比较常用的是使用RelativeLayout布局以及重用布局使用include标签,另外listView 或者是GridView的优化,以及ViewHolder的使用都比较频繁,希望大家掌握,另外<merge>标签和<viewstub>标签也视情况使用。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值