Android 性能优化方法

版权声明:博主原创欢迎分享学习 https://blog.csdn.net/qXing123456789/article/details/84030566

Android 性能优化方法

开发中常会做一些性能优化,主要优化内容包括布局层级优化,绘制优化,内存泄露优化(音频,视频,io等回收),响应速度优化,ListView优化,Bitmap优化,线程优化以及一些性能优化,在面试中面试官也会经常问到该点 . 前面博文我收集的各大厂等面试题

布局优化

布局优化思想,尽量减少布局文件的层级,层级少,意味Android绘制时的工作量少了,程序的性能自然提高了.

  1. 删除布局中无用的控件和层级
  2. 有选择使用性能较低的ViewGroup,如:RelativeLayout
  3. 优先使用LinearLayout,相对RelativeLayout,其功能比较简单,花费较少的CPU时间
  4. 需要复杂嵌套实现效果时,这种情况下建议采用RelativeLayout
  5. 采用标签在于布局重用,标签降低减少布局层级和ViewStub按需加载
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="@color/main_background_color"
              android:fitsSystemWindows="true"
              android:orientation="vertical">

    <include layout="@layout/layout_toolbar"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="10dp"
        android:layout_weight="1"
        android:orientation="vertical">

        <!--个人信息-->
        <RelativeLayout
            android:id="@+id/rl_setting_user_message"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="@color/white">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="15dp"
                android:text="个人信息"
                android:textColor="@color/text_color_black"
                android:textSize="16sp"/>

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="15dp"
                android:src="@mipmap/arrow"/>

        </RelativeLayout>

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:src="@color/button_stroke"/>

        <!--账号安全-->
        <RelativeLayout
            android:id="@+id/rl_setting_user_safe"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="@color/white">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="15dp"
                android:text="账号安全"
                android:textColor="@color/text_color_black"
                android:textSize="16sp"/>

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="15dp"
                android:src="@mipmap/arrow"/>

        </RelativeLayout>

        <!--消息通知-->
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginTop="15dp"
            android:background="@color/white">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="15dp"
                android:text="消息通知"
                android:textColor="@color/text_color_black"
                android:textSize="16sp"/>

            <Switch
                android:id="@+id/switch_message"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="15dp"
                android:showText="false"
                android:textOff=""
                android:textOn=""
                android:thumb="@drawable/swtich_thumb_selector"
                android:track="@drawable/swtich_track_selector"
                />

        </RelativeLayout>

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:src="@color/button_stroke"/>

        <!--音效-->
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="@color/white">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="15dp"
                android:switchMinWidth="40dp"
                android:switchPadding="10dp"
                android:text="音效"
                android:textColor="@color/text_color_black"
                android:textOff="开"
                android:textOn="关"
                android:textSize="16sp"
                android:typeface="normal"/>

            <Switch
                android:id="@+id/switch1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="15dp"
                android:gravity="center_vertical"
                android:showText="false"
                android:textOff=""
                android:textOn=""
                android:thumb="@drawable/swtich_thumb_selector"
                android:track="@drawable/swtich_track_selector"
                />

        </RelativeLayout>

        <!--版本号-->
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginTop="15dp"
            android:background="@color/white">

            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="15dp"
                android:text="版本"
                android:textColor="@color/text_color_black"
                android:textSize="16sp"/>

            <TextView
                android:id="@+id/version"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="15dp"
                android:textColor="@color/color_bfbfbf"
                android:textSize="16sp"/>

        </RelativeLayout>

    </LinearLayout>

    <Button
        android:id="@+id/bt_login_out"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginBottom="15dp"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:background="#ff4a2c"
        android:gravity="center"
        android:text="登出账号"
        android:textColor="@color/white"
        android:textSize="18sp"/>


</LinearLayout>

绘制优化

绘制优化是指View的onDraw方法要避免执行大量的操作,如下三点

  1. onDraw中不要创建新的局部对象,因为onDraw方法可能会被频繁调用,这样就会在一瞬间产生大量的临时对象,这不仅占用了过多的内存而且还会导致系统更加频繁gc,降低了程序的执行效率
  2. onDraw方法中不要做耗时的任务,也不能执行复杂的循环操作,尽管每次循环都很轻量级,但是大量的循环任然十分抢占CPU的时间片,这回造成View的绘制过程不流畅.
  3. Google官方给出的性能优化典范中的标准,View的绘制帧率保证60fps是最佳的,这就要求每帧的绘制时间不超过16ms(16 = 1000/60),虽然程序很难保证16ms这个时间,但是尽量降低onDraw方法的复杂度总是切实有效的.

内存泄露优化

内存泄露在开发过程中是一个需要重视的问题,但是由于内存泄露问题 对开发人员的经验和开发意识有较高的要求,因此这也是开发人员最容易犯的错误之一.内存泄露的优化分为两个方面,一方面是开发过程中避免写出有内存泄露的代码.另一方面是通过一些分析工具找出潜在的内存泄露

  1. 静态变量导致的内存泄露,(在dalvik虚拟机中,static变量所指向的内存引用,如果不把它设置为null,GC是永远不会回收这个对象的),处理: 对象=null;
  2. 单例模式导致的内存泄露,如下

单例模式导致的内存泄露:Activty是间接继承于Context的,当这Activity退出时,Activity应该被回收, 但是单例中又持有它的引用,导致Activity回收失败,造成内存泄漏。

package com.kx.singleinstance;

import android.content.Context;

/**
 * @ 创建:   kx
 * @ 时间:    2018/11/13
 * @ 描述:
 */

public class AppManager  {

    private static AppManager instance;
    
    private  Context mContext;

    public AppManager(Context context) {
        mContext = context;
    }

    public  static AppManager getInstance(Context context){
        if(instance == null){
            instance = new AppManager(context);
        }
        return  instance;
    }
}

单例模式导致的内存泄露改进:使用Applicaton的Context,而我们单例的生命周期和应用的一样长,这样就防止了内存泄漏。

package com.kx.singleinstance;

import android.content.Context;

/**
 * @ 创建:   kx
 * @ 时间:    2018/11/13
 * @ 描述:
 */

public class AppManager  {


    private static AppManager instance;
    
    private  Context mContext;

    public AppManager(Context context) {
        //使用Applicaton的Context,而我们单例的生命周期和应用的一样长,这样就防止了内存泄漏。
        mContext = context.getApplicationContext();
    }

    public  static AppManager getInstance(Context context){
        if(instance == null){
            instance = new AppManager(context);
        }
        return  instance;
    }
}

  1. 属性动画导致的内存泄露,属性动画无限循环动画,Activity与View相互持有,导致Activity无法释放. 解决: onDestroy 对动画 animator.cancel()来停止动画

响应速度优化

响应速度优化的核心思想是避免在主线程中做耗时操作,这里具体可参考前面的文章.耗时操作放在线程中去执行,即采用异步的方式执行耗时操作.响应速度过慢更多地体现在Activity的启动速度上面,如果在主线中做太多事情,会导致Activity启动时出现黑屏现象,甚至出现ANR, Android规定,Activity如果5秒钟之内无法响应屏幕触摸事件或者键盘输入时间就会出现ANR,而BroadcastReceiver如果10秒钟之内还未执行完操作也会出现ANR.

ListView和Bitmap优化

listview优化

  1. convertView的使用,主要优化加载布局问题

  2. 内部类ViewHolder的使用,采用ViewHolder并避免在getView中执行耗时操作

  3. 滑动的时候不载入图片

    在ListView滑动的时候载入图片,那样会使ListView变得卡顿,所以我们须要再监听器里面监听ListView的状态。假设滑动的时候,停止载入图片,假设没有滑动,则開始载入图片

listView.setOnScrollListener(new OnScrollListener() {

            @Override
            public void onScrollStateChanged(AbsListView listView, int scrollState) {
                    //停止载入图片 
                    if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
                            imageLoader.stopProcessingQueue();
                    } else {
                    //開始载入图片
                            imageLoader.startProcessingQueue();
                    }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                    // TODO Auto-generated method stub

            }
    });
  1. 将ListView的scrollingCache和animateCache设置为false

    A.scrollingCache: scrollingCache本质上是drawing cache,你能够让一个View将他自己的drawing保存在cache中(保存为一个bitmap),这样下次再显示View的时候就不用重画了,而是从cache中取出。默认情况下drawing cahce是禁用的。由于它太耗内存了,可是它确实比重画来的更加平滑。而在ListView中,scrollingCache是默认开启的,我们能够手动将它关闭。

    B.animateCache: ListView默认开启了animateCache,这会消耗大量的内存,因此会频繁调用GC,我们能够手动将它关闭掉

<ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:divider="@color/list_background_color"
        android:dividerHeight="0dp"
        android:listSelector="#00000000"
        android:scrollingCache="false"
        android:animationCache="false"
        android:smoothScrollbar="true"
        android:visibility="gone" />
  1. 降低item的布局的深度

    尽量降低item布局深度,由于当滑动ListView的时候,这回直接导致測量与绘制,因此会浪费大量的时间。所以我们应该将一些不必要的布局嵌套关系去掉。

  2. 分批加载与分页加载相结合

线程优化

线程优化的核心思想是采用线程池,避免程序中存在大量的Thread.线程池可以重用内部的线程,从而避免了线程的创建和销毁所带来的性能开销,同时线程池还能有效地控制线程池的最大并发数,避免大量的线程因互相抢占系统资源从而导致阻塞现象的发生.因此在实际开发中,我们要尽量采用线程池,而不是每次都要创建一个Thread对象

心灵激励

激励:为自己技术增值,量变引起质变.博主依稀记得当前的语文老师说的一句话:“态度决定高度”,博主想对所有的读者说"过去的已经过去,你的未来由你现在把握".

尾言

本文如有错误或不当之处,欢迎读者留言斧正,互相交流学习,博主不胜感激.联系邮箱[email protected]

猜你喜欢

转载自blog.csdn.net/qXing123456789/article/details/84030566