天天看点

安卓性能优化—布局优化

性能优化是开发中必不可少的,大概可以从内存、布局以及app启动时间等方面进行优化,本篇文章介绍一些布局优化的方法;

1、合理选择布局

新建activity时,默认的布局是RelativeLayout ,WHY?看看谷歌官方的介绍https://developer.android.google.cn/guide/topics/ui/layout/relative.html

A RelativeLayout is a very powerful utility for designing a user interface because it can eliminate nested view groups and keep your layout hierarchy flat, which improves performance. If you find yourself using several nested LinearLayout groups, you may be able to replace them with a single RelativeLayout.

           

Google的意思是 RelativeLayout 在性能上更好,但是在开发中还是要根据实际情况选择适当的布局;

1. RelativeLayout 布局灵活一些尽量使用padding代替margin;

2. 实现复杂的布局时,由于 RelativeLayout 所需要的嵌套层次少,所以可能大概也许性能会好一些。

3. 对于简单的布局,或者使用 LinearLayout 的嵌套布局层次不多的情况下。还是推荐 使用 inearLayout 来实现。 因为 LinearLayout 布局性能更高一点,为什么? 因为 RelativeLayout 布局需要至少计算两次。

2.使用include标签

include标签常用于将布局中的公共部分提取出来,达到xml文件复用的效果;

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <include layout="@layout/test_layout" />
</RelativeLayout>
           

3.使用merge标签

merge标签是作为include标签的一种辅助扩展来使用,它的主要作用是为了防止在引用布局文件时产生多余的布局嵌套。Android渲染需要消耗时间,布局越复杂,性能就越差。如上述include标签引入了之前的LinearLayout之后导致了界面多了一个层级。

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

    <ImageView        
        android:id="@+id/iv_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:src="@mipmap/ic_launcher" />

    <TextView      
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="16dp"
        android:layout_toRightOf="@+id/iv_image"
        android:text="这个是MergeLayout"
        android:textSize="16sp" />
</merge>
           

activity_main布局中使用include标签:

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.jared.layoutoptimise.MainActivity">

    <include layout="@layout/test_layout" />
</RelativeLayout>
           

在item_merge_layout布局中使用了merge标签,所以此时activity_main布局会减少一层原来test_layout的最外层布局;

4、使用viewstub标签

viewstub是view的子类。他是一个轻量级View, 隐藏的,没有尺寸的View。他可以用来在程序运行时简单的填充布局文件。接着简单试用下viewstub吧。首先修改activity_main.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <include        
        android:id="@+id/layout_merge"
        layout="@layout/item_merge_layout" />

    <ViewStub       
        android:id="@+id/vs_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout="@layout/item_merge_layout"
        android:layout_below="@+id/layout_merge"
        android:layout_marginTop="10dp" />
</RelativeLayout>
           

使用ViewStub标签时要注意 ViewStub只能被inflate一次,否则会抛出ViewStub must have a non-null ViewGroup viewParent异常;

Android最新的布局方式ConstaintLayout

ConstraintLayout允许你在不适用任何嵌套的情况下创建大型而又复杂的布局。它与RelativeLayout非常相似,所有的view都依赖于兄弟控件和父控件的相对关系。但是,ConstraintLayout比RelativeLayout更加灵活,目前在AndroidStudio中使用也十分方便,就和以前的拖拉控件十分相似。那么怎么使用呢?

  首先是安装Constaintlayout了。Android SDK -> SDK Tools -> Support Repository中的ConstrainLayout for Android和Solver for ConstaintLayout。

添加依赖:

接下来就可以轻松愉快的使用ConstaintLayout实现你的xml布局了;

布局中常用的小技巧:

转自http://blog.csdn.net/qq_17766199/article/details/52863741

  1. TextView同时显示图片和文字
<TextView
        android:drawableLeft="@drawable/icon_1"
        android:drawableRight="@drawable/icon_2"
        android:drawablePadding="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"        
        android:text="联系人"      
        android:gravity="center_vertical"        
        android:layout_height="50dp" />
           

2 TextView的行间距

<TextView
        android:textSize="14dp"
        android:lineSpacingExtra="8dp"
        android:gravity="center_vertical"
        android:text="揽件方式:上门取件\n快递公司:顺丰快递\n预约时间:9月6日 立即取件\n快递费用:等待称重确定价格"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
           

lineSpacingExtra属性代表的是行间距,他默认是0,是一个绝对高度值。同时还有lineSpacingMultiplier属性,它代表行间距倍数,默认为1.0f,是一个相对高度值。

3. 使用Spannable或Html.fromHtml实现富文本;

String text = String.format("¥%1$s  门市价:¥%2$s", , );
 int z = text.lastIndexOf("门");
 SpannableStringBuilder style = new SpannableStringBuilder(text);
 style.setSpan(new AbsoluteSizeSpan(DisplayUtil.dip2px(mContext,)), , , Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //字号
 style.setSpan(new ForegroundColorSpan(Color.parseColor("#afafaf")), z, text.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //颜色
 style.setSpan(new AbsoluteSizeSpan(DisplayUtil.dip2px(mContext,)), z, text.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //字号

 tv.setText(style);
           

4.用LinearLayout自带的分割线

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:divider="@drawable/divider"
    android:showDividers="middle">

    <TextView
        android:drawableLeft="@drawable/icon_1"
        android:drawableRight="@drawable/icon_4"
        android:drawablePadding="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textSize="16sp"
        android:text="我的卡券"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

    <TextView
        android:drawableLeft="@drawable/icon_2"
        android:drawableRight="@drawable/icon_4"
        android:drawablePadding="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textSize="16sp"
        android:text="地址管理"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

    <TextView
        android:drawableLeft="@drawable/icon_3"
        android:drawableRight="@drawable/icon_4"
        android:drawablePadding="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textSize="16sp"
        android:text="检查更新"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

</LinearLayout>
           

现的核心部分其实是LinearLayout的这两行:

android:divider="@drawable/divider"
android:showDividers="middle"
           

其中divider.xml是分隔线样式:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">

    <size android:width="1dp"
          android:height="1dp"/>

    <solid android:color="#e1e1e1"/>

</shape>
           

showDividers 是分隔线的显示位置,beginning、middle、end分别代表显示在开始位置,中间,末尾。

还有dividerPadding属性这里没有用到,意思很明确给divider添加padding;

继续阅读