美文网首页
Android性能优化

Android性能优化

作者: 玄策 | 来源:发表于2017-10-12 11:28 被阅读18次

    目录

    • 1)布局优化
    • 2)绘制优化
    • 3)ListView和Bitmap优化
    • 4)线程优化
    • 5)App启动优化
    • 6)内存优化
    • 7)电量优化
    • 8)网络优化
    • 9)性能优化工具
    • 10)响应速度优化和ANR日志分析
    • 11)一些性能优化建议

    1)布局优化

    布局优化就是尽量减少布局文件的层数。

    方式 说明
    去掉其他不必要的背景 overdraw (过渡绘制)的关键点在于一个像素被绘制了几次
    <include> 可以将一个指定的布局文件加载到当前布局文件中
    <merge> 一般和<include>一起使用,可以少一层嵌套
    ViewStub 继承View,更轻量级且宽高为0。可以做到按需加载以提升性能,而不是界面初始化的时候加载,如网络异常的界面。
    <include layout="@layout/merge_button">
    
    // ~res/layout/merge_button.xml
    <merge xmlns:android="http://schemas.android.com/apk/res/android">
      <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
    </merge>
    
    <ViewStub
      android:id="@+id/stub_import"
      android:layout="layout/xxx"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
    />
    
    //通过setVisibility后,ViewStub就会被他内部的布局替换掉
    (ViewStub)findViewById(R.id.stub_import).setVisibility(View.VISIBLE)
    
    工具 说明
    Layout Inspector Tools -> Android -> Layout Inspector
    调试GPU过度绘制功能 手机-开发者选项

    2)绘制优化

    Android 屏幕刷新机制
    android屏幕刷新显示机制
    Google的官方性能标准,View的绘制帧率保持在60fps为最佳,这就要求每一帧的绘制时间不超过16ms(1000/60)。

    正常绘制
    丢帧,卡顿
    View的onDraw()要避免大量操作
    • 因为onDraw()会被频繁调用,所以此方法内不要创建局部变量。大量局部变量会造成频繁GC,频繁GC也会造成卡顿,因为GC会中断程序运行。
    • onDraw()不要做耗时任务

    3)ListView和Bitmap优化

    请参阅之前笔记。

    • ListView 避免在getView()中执行耗时操作,其次快速滑动时无需开启大量异步任务去请求图片。
    • Bitmap 图片压缩和缓存

    4)线程优化

    • 采用线程池,避免大量的Thread。

    5)App启动优化

    5.1) 在Application初始化的时候执行了大量的操作

    • 通过traceview检查方法执行时长
    • 采用IntentService在线程中加载操作
    //~ MainApplication.java
        public void onCreate()
        {
            Debug.startMethodTracing("Application");
    
            super.onCreate();
    
            //ARouter init
            if (BuildConfig.DEBUG) {           // 这两行必须写在init之前,否则这些配置在init过程中将无效
                ARouter.openLog();     // 打印日志
                ARouter.openDebug();   // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
            }
            ARouter.init(this); 
            //jpush init
            JPushInterface.init(this);
            //shareSDK init
            ShareSDK.initSDK(this); 
            //RNinit
            SoLoader.init(this, /* native exopackage */ false);
    
            //LeakCanary
            if (LeakCanary.isInAnalyzerProcess(this)) {
                // This process is dedicated to LeakCanary for heap analysis.
                // You should not init your app in this process.
                return;
            }
            LeakCanary.install(this);
    
            Debug.stopMethodTracing();
        }
    
    运行后可以在sdcard中找到trace
    打开 也可以Monitor打开

    5.2)首屏加载不要耗时过长

    App没有完全起来时, 屏幕会一直显示一块空白的窗口。
    Android最新的Material Design建议我们使用一个placeholder UI来展示给用户直至App加载完毕

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- 底层白色 -->
        <item android:drawable="@android:color/white" />
    
        <!-- 顶层Logo居中 -->
        <item>
            <bitmap
                android:gravity="center"
                android:src="@drawable/ic_launcher" />
        </item>
    </layer-list>
    
    
    <style name="SplashTheme" parent="AppTheme">
        <item name="android:windowBackground">@drawable/logo_splash</item>
    </style>
    
    //启动页
    public class SplashActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            startActivity(new Intent(this,WelcomeActivity.class));
            finish();
        }
    }
    
            <activity android:name=".ui.SplashActivity"
                android:label="@string/app_name"
                android:screenOrientation="portrait"
                android:theme="@style/SplashTheme">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
    

    6)内存优化

    内存抖动:短时间大量的对象被创建又释放,会造成锯齿状内存,产生频繁的GC,造成卡顿。
    解决:1-避免循环创建对象;2-onDraw不要创建对象;3-对于无法避免可使用对象池。

    一个永远不会被使用的对象,因为一些引用没有断开,没有满足GC条件,导致不会被回收

    • 静态变量(如一个静态变量持有了Activity的引用,将会导致Activity无法销毁)
    • 非静态内部类(非静态内部类如Handler或Runnable会维持一个到外部类实例的引用,可以使用静态内部类和WeakReference代替)
    • Handler临时性内存泄露(非静态的Handler持有外部如Activity引用,而MQ又持有Handler的引用)
    • 资源未关闭( Cursor、SQLiteDatabase,io流)
    • 广播和监听器没有反注册(unregister,removelistener)
    • adapter未使用contentView缓存

    7)电量优化

    adb bugreport > bugreport.txt
    

    使用 Battery Historian.来导入bugreport通过图形界面查看电量消耗。

    • 优化网络请求
    • 监听手机充电状态(如手机充电时进行一些文件上传,用户数据同步等操作)
    IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    Intent batteryStatus = context.registerReceiver(null, ifilter);
    int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
    boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                         status == BatteryManager.BATTERY_STATUS_FULL;
    
    • 6.0 Doze模式会延迟后台网络或cpu来减少电量消耗

    8)网络优化

    • Android Porfiler监控网络请求
    • 更好的接口设计,更合理的接口调用。还可以打包网络请求
    • request Cache-Control
    • 弱网测试
    • 图片size

    9)性能优化工具

    性能优化工具
    • StrictMode -严格模式
            // 分别为MainThread和VM设置Strict Mode
            if (BuildConfig.DEBUG) {
                //线程策略
                StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                        .detectAll() //侦测一切潜在违规
                        .detectDiskReads() //侦测磁盘读
                        .detectDiskWrites() //侦测磁盘写
                        .detectNetwork()    //侦测网络操作
                        .detectCustomSlowCalls() //侦测自定义的耗时操作
                        .penaltyDialog() //违规时,向开发者显示一个恼人的Dialog对话框
                        .build());
    
                //虚拟机策略
                StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                        .detectLeakedSqlLiteObjects()
                        .detectLeakedClosableObjects() //当显式中止方法调用之后,假如可被Closeable类或其他的对象没有被关闭。
                        .detectLeakedRegistrationObjects()
                        .detectActivityLeaks()
                        .penaltyLog() //违规时,将违规信息写入系统日志
                        .build());
            }
    

    • Lint检查
      Analyze->Inspect Code


      Lint检查

    • HierarchyViewer的替代Layout Inspector
      Tools -> Android -> Layout Inspector


      Layout Inspector

    • TraceViewer

    • Android Porfiler


      Android Porfiler

    • 调试GPU过度绘制功能 手机-开发者选项



    10)响应速度优化和ANR日志分析

    组件 ANR时间
    Activity 5秒
    BroadcastReceiver 10秒
    Service 20秒

    adb pull /data/anr/traces.txt 文件可以看到ANR日志


    11)一些性能优化建议

    • 避免创建过多对象
    • 避免过多使用枚举,枚举占用内存空间大
    • 常量使用static final修饰
    • 使用Android特有数据结构,如SpaceArray何Pair等
    • 适当使用软引用和弱引用
    • 内存缓存和磁盘缓存
    • 尽量采用静态内部类,避免由于内部类导致的内存泄漏

    参考资料

    Android应用优化最全指南和清单
    Android App优化之性能分析工具
    Android APP 性能优化的一些思考

    ---`

    相关文章

      网友评论

          本文标题:Android性能优化

          本文链接:https://www.haomeiwen.com/subject/huxurxtx.html