首页 > 系统 > Android > 正文

Android性能优化

2019-11-08 00:05:11
字体:
来源:转载
供稿:网友

###重用

include

< include>标签可以在一个布局中引入另外一个布局,这个的好处显而易见。类似于我们经常用到的工具类,随用随调。便于统一修改使用。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    android:orientation="vertical">    <include layout="@layout/toolbar" />    ...省略</LinearLayout>

而我toolbar的布局是单独的一个,可以在任务需要的地方进行include

    <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/toolbar"    android:layout_width="match_parent"    android:layout_height="?attr/actionBarSize"    android:background="?attr/colorPRimary"    android:navigationIcon="@drawable/back"    app:layout_scrollFlags="scroll|enterAlways"    app:navigationIcon="@drawable/back"    app:popupTheme="@style/ThemeOverlay.AppCompat.Light">    <!--<RelativeLayout-->    <!--android:layout_width="match_parent"-->    <!--android:layout_height="wrap_content"-->    <!--android:gravity="center">-->    <TextView        android:id="@+id/toolbar_tv"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:layout_gravity="center"        android:ellipsize="end"        android:maxEms="9"        android:singleLine="true"        android:text="@string/gallery_app_name"        android:textColor="@android:color/white"        android:textSize="18sp" />    <FrameLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="right">        <TextView            android:id="@+id/title_right"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentRight="true"            android:layout_centerVertical="true"            android:layout_gravity="right"            android:layout_marginRight="10dp"            android:padding="10dp"            android:textColor="@android:color/white"            android:textSize="15sp" />        <ImageView            android:id="@+id/image_right"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentRight="true"            android:layout_centerVertical="true"            android:layout_gravity="right"            android:layout_marginRight="10dp"            android:padding="10dp" />    </FrameLayout></android.support.v7.widget.Toolbar>

2.合并


2.1 减少嵌套

首先我们心中要有一个大原则:尽量保持布局层级的扁平化。在这个大原则下我们要知道:在不影响层级深度的情况下,使用LinearLayout而不是RelativeLayout。因为RelativeLayout会让子View调用2次onMeasure,LinearLayout 在有weight时,才会让子View调用2次onMeasure。Measure的耗时越长那么绘制效率就低。

如果非要是嵌套,那么尽量避免RelativeLayout嵌套RelativeLayout。这简直就是恶性循环,丧心病狂

2.2 使用merge

< merge/>主要用来去除不必要的FrameLayout。它的使用最理想的情况就是你的根布局是FrameLayout,同时没有使用background等属性。这时可以直接替换。因为我们布局外层就是FrameLayout,直接“合并”。

PS: 上面已经说了同时## 没有使用background等属性。 ##

2.3 用TextView同时显示图片和文字

这种效果很常见,一般实现方法是这样。(貌似没人这样写吧,哈哈)

<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <LinearLayout        android:orientation="horizontal"        android:background="@color/white"        android:layout_width="match_parent"        android:layout_height="50dp">        <ImageView            android:layout_marginLeft="10dp"            android:layout_width="wrap_content"            android:src="@drawable/icon_1"            android:layout_height="match_parent" />        <TextView            android:paddingLeft="10dp"            android:paddingRight="10dp"            android:textSize="16sp"            android:text="我的卡券"            android:gravity="center_vertical"            android:layout_width="0dp"            android:layout_weight="1"            android:layout_height="match_parent" />        <ImageView            android:layout_marginRight="10dp"            android:src="@drawable/icon_4"            android:layout_width="wrap_content"            android:layout_height="match_parent"/>    </LinearLayout></LinearLayout>    

这里可以直接使用textview的drawable的right|left|top|bottom等

<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <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" /></LinearLayout>

你没有看错,少了两个ImageView和去除嵌套LinearLayout。效果不用说一样一样的

这里也可以动态设置图片的。setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)可以让我们动态去设置图片。

2.4 使用textview的行间距

想要实现的

我平时如果遇到这种之前是直接用下面的布局实现的

<LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_height="100dp"    android:background="@color/white"    android:layout_width="match_parent"    xmlns:tools="http://schemas.android.com/tools">    <ImageView        android:padding="25dp"        android:src="@drawable/kd_1"        android:layout_width="100dp"        android:layout_height="100dp"/>    <LinearLayout        android:layout_width="match_parent"        android:orientation="vertical"        android:layout_height="100dp">        <TextView            tools:text="揽件方式:上门取件"            android:gravity="center_vertical"            android:layout_width="match_parent"            android:layout_height="25dp"/>        <TextView            tools:text="快递公司:顺丰快递"            android:gravity="center_vertical"            android:layout_width="match_parent"            android:layout_height="25dp"/>        <TextView            tools:text="预约时间:9月6日 立即取件"            android:gravity="center_vertical"            android:layout_width="match_parent"            android:layout_height="25dp"/>        <TextView            tools:text="快递费用:等待称重确定价格"            android:gravity="center_vertical"            android:layout_width="match_parent"            android:layout_height="25dp"/>    </LinearLayout></LinearLayout

优化后代码:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_height="100dp"android:background="@color/white"android:layout_width="match_parent"><ImageView    android:padding="25dp"    android:src="@drawable/kd_1"    android:layout_width="100dp"    android:layout_height="match_parent"/><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" /></LinearLayout>

老规矩,效果一样一样的。可以看到我们仅仅利用Android:lineSpacingExtra=”8dp”这一行代码就省去了3个TextView,如果行数更多呢?是不是方便多了。

其中:lineSpacingExtra属性代表的是行间距,他默认是0,是一个绝对高度值。同时还有>lineSpacingMultiplier属性,它代表行间距倍数,默认为1.0f,是一个相对高度值。我们来使>用一下:

<LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_height="100dp"    android:background="@color/white"    android:layout_width="match_parent">    <ImageView        android:padding="25dp"        android:src="@drawable/kd_1"        android:layout_width="100dp"        android:layout_height="100dp"/>    <TextView        android:textSize="14dp"        android:lineSpacingMultiplier="1.3"        android:gravity="center_vertical"        android:text="揽件方式:上门取件/n快递公司:顺丰快递/n预约时间:9月6日 立即取件/n快递费用:等待称重确定价格"        android:layout_width="match_parent"        android:layout_height="match_parent" /></LinearLayout>

当然了这两条属性可以同时使用,查看源码可以知道,他们的高度计算规则为mTextPaint.getFontMetricsInt(null) * 行间距倍数 + 行间距

####使用Spannable或Html.fromHtml

如果实现上图红框中的效果,笨办法就是写三个TextView,“¥”,“价格”,“门市价”分别实现,其实用一个TextVIew就可以实现,类似如下代码:

String text = String.format("¥%1$s  门市价:¥%2$s", 18.6, 22);int z = text.lastIndexOf("门");SpannableStringBuilder style = new SpannableStringBuilder(text);style.setSpan(new AbsoluteSizeSpan(DisplayUtil.dip2px(mContext,14)), 0, 1, 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,14)), z, text.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //字号tv.setText(style);

####用LinearLayout自带的分割线

还记得上文用TextView同时显示图片和文字中的例子吗?我们可以看到每个条目之间都是有一根分隔线的,那么怎么实现呢?别人我不知道,反正我原来是用一个View设置高度实现的。相信一定有人和我一样。

那么老办法我就不演示了,直接上代码:

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

这里核心实现:

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

其中divider.xml是分隔线样式

<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。感兴趣可以试试。

####Space控件

还是接着上面的例子,如果要给条目中间添加间距,怎么实现呢?当然也很简单,比如添加一个高10dp的View,或者使用android:layout_marginTop=”10dp”等方法。但是增加View违背了我们的初衷,并且影响性能。使用过多的margin其实会影响代码的可读性。

这时你就可以使用Space,他是一个轻量级的。我们可以看下源码:

public final class Space extends View {    /**     * {@inheritDoc}     */    public Space(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);        if (getVisibility() == VISIBLE) {            setVisibility(INVISIBLE);        }    }    /**     * {@inheritDoc}     */    public Space(Context context, AttributeSet attrs, int defStyleAttr) {        this(context, attrs, defStyleAttr, 0);    }    /**     * {@inheritDoc}     */    public Space(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    /**     * {@inheritDoc}     */    public Space(Context context) {        //noinspection NullableProblems        this(context, null);    }    /**     * Draw nothing.     *     * @param canvas an unused parameter.     */    @Override    public void draw(Canvas canvas) {    }    /**     * Compare to: {@link View#getDefaultSize(int, int)}     * If mode is AT_MOST, return the child size instead of the parent size     * (unless it is too big).     */    private static int getDefaultSize2(int size, int measureSpec) {        int result = size;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        switch (specMode) {            case MeasureSpec.UNSPECIFIED:                result = size;                break;            case MeasureSpec.AT_MOST:                result = Math.min(size, specSize);                break;            case MeasureSpec.EXACTLY:                result = specSize;                break;        }        return result;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(                getDefaultSize2(getSuggestedMinimumWidth(), widthMeasureSpec),                getDefaultSize2(getSuggestedMinimumHeight(), heightMeasureSpec));    }}

可以看到在draw方法没有绘制任何东西,那么性能也就几乎没有影响。

<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|beginning|end">    <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" />    <Space        android:layout_width="match_parent"        android:layout_height="15dp"/>    <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>

欢迎加入技术QQ群:364595326


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表