Android APP启动优化

文章目录

  • 1 系统的启动
  • 2 Launcher启动
  • 3 application的启动
  • 4 黑白屏问题
  • 5 启动时间的查看
  • 6 Trace工具分析代码执行时间

技术点:

  1. 传说中的黑白屏问题优化
  2. 黑白屏在商业APP中的价值
  3. App启动流程
  4. 如何使用Traceview工具对优化定位处理

1 系统的启动

Android APP启动优化_第1张图片

  1. 打开电源,引导芯片代码加载引导程序BootLoader到RAM中去执行
  2. BootLoader把操作系统拉起来
  3. Linux内核启动开始系统设置,找到一个init.rc文件启动初始化进程
  4. init进程初始化和启动属性服务,之后开启Zygote进程
  5. Zygote开始创建JVM并注册JNI方法,开启SystemServer
  6. 启动Binder线程池和SystemServiceManager,并启动各种服务
  7. AMS启动Launcher

2 Launcher启动

  1. 通过adb shell dumpsys activity activities查看当前的activity名

先后台将所有app关闭,然后打开一个app。我的app中首页是MainActivity。

  Running activities (most recent first):
    TaskRecord{4145f710 #270 A com.hongx.hxlsn01 U 0}
      Run #2: ActivityRecord{4102f8d0 u0 com.hongx.hxlsn01/.MainActivity}
    TaskRecord{4170c6d8 #2 A com.huawei.android.launcher U 0}
      Run #1: ActivityRecord{4170a3f8 u0 com.huawei.android.launcher/.Launcher}
    TaskRecord{41e3ffe8 #157 I com.android.settings/.Settings$UsbSettingsActivity U 0}
      Run #0: ActivityRecord{4155e5c8 u0 com.android.settings/.UsbSettings}

  mResumedActivity: ActivityRecord{4102f8d0 u0 com.hongx.hxlsn01/.MainActivity}
  mFocusedActivity: ActivityRecord{4102f8d0 u0 com.hongx.hxlsn01/.MainActivity}
  mLastPausedActivity: ActivityRecord{4170a3f8 u0 com.huawei.android.launcher/.Launcher}

Running activities 表示正在运行的activity。
mLastPausedActivity 表示已经暂停的activity 为Launcher。


再去按下home键,dumpsys activity activities 后查看当前的activity名

  Running activities (most recent first):
    TaskRecord{4170c6d8 #2 A com.huawei.android.launcher U 0}
      Run #2: ActivityRecord{4170a3f8 u0 com.huawei.android.launcher/.Launcher}
    TaskRecord{4145f710 #270 A com.hongx.hxlsn01 U 0}
      Run #1: ActivityRecord{4102f8d0 u0 com.hongx.hxlsn01/.MainActivity}
    TaskRecord{41e3ffe8 #157 I com.android.settings/.Settings$UsbSettingsActivity U 0}
      Run #0: ActivityRecord{4155e5c8 u0 com.android.settings/.UsbSettings}

  mResumedActivity: ActivityRecord{4170a3f8 u0 com.huawei.android.launcher/.Launcher}
  mFocusedActivity: ActivityRecord{4170a3f8 u0 com.huawei.android.launcher/.Launcher}
  mLastPausedActivity: ActivityRecord{4102f8d0 u0 com.hongx.hxlsn01/.MainActivity}

从输出中可以看出,正在运行的activity为Launcher,已暂停的activity变成了MainActivity。

Launcher 概述
系统启动的最后一步是启动一个应用程序用来显示系统中已经安装的应用程序,这个应用程序就叫作 Launcher。Launcher 在启动过程中会请求 PackageManagerService 返回系统中已经安装的应用程序的信息,并将这些信息封装成一个快捷图标列表显示在系统屏幕上,这样用户可以通过点击这些快捷图标来启动相应的应用程序。

Android APP启动优化_第2张图片


3 application的启动

E:\tools\android-src\android-6.0.1_r1\packages\apps\
Launcher2\src\com\android\launcher2\Launcher.java

当我们用手点击一个图标时,就到了这个类public final class Launcher extends Activity
执行onClick(View view)方法,会把这个应用的相关信息传入
先获取一个intent—>startActivitySafely(v, intent, tag)–》startActivity(v, intent, tag);–>startActivity(intent);

startActivity(intent)会开一个APP进程

Android APP启动优化_第3张图片
ActivityThread.java做为入口 用attach开启app 再加载application和activity
thread.attach(false);—》mgr.attachApplication(mAppThread)会通过远端进程去
回调private void handleBindApplication(AppBindData data)
Application app = data.info.makeApplication(创建Application对象
mInstrumentation.callApplicationOnCreate(app);----》 app.onCreate();

4 黑白屏问题

res/values/styles.xml文件

白屏    
    
    
再在功能清单中的单独activity下设置
QQ中的用法   
true
@null

5 启动时间的查看

  • 4.4版本以后Logcat 输入Displayed筛选系统日志 不过滤信息No Filters

  • 4.4以前 adb shell am start -W com.lqr.wechat/com.lqr.wechat.activity.SplashActivity

adb shell am start -W com.lqr.wechat/com.lqr.wechat.activity.SplashActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.lqr.wechat/.activity.SplashActivity }
Status: ok
Activity: com.lqr.wechat/.activity.SplashActivity
ThisTime: 883
TotalTime: 883
WaitTime: 915
Complete

Android APP启动优化_第4张图片

  1. ThisTime:最后一个启动的Activity的启动耗时;
  2. TotalTime:自己的所有Activity的启动耗时;
  3. WaitTime: ActivityManagerService启动App的Activity时的总时间(包括当前Activity的onPause()和自己Activity的启动)。

查看进程   adb shell ps

在输出中找到进程

u0_a533      25343  1275 4484104 190652 0                   0   efg  S com.lqr.wechat
u0_a533      25368  1275 4388180  97448 0                   0   efg  S com.lqr.wechat:core
u0_a533      25401  1275 4385168  93684 0                   0   ebg  S com.lqr.wechat:cosine
u0_a533      25436     1 4389532  41984 0                   0   ebg  S com.lqr.wechat:cosine

Am.java

AM路径\frameworks\base\cmds\am\src\com\android\commands\am

            IActivityManager.WaitResult result = null;
            int res;
            final long startTime = SystemClock.uptimeMillis();
            ActivityOptions options = null;
            if (mStackId != INVALID_STACK_ID) {
                options = ActivityOptions.makeBasic();
                options.setLaunchStackId(mStackId);
            }
            if (mWaitOption) {
                result = mAm.startActivityAndWait(null, null, intent, mimeType,
                        null, null, 0, mStartFlags, profilerInfo,
                        options != null ? options.toBundle() : null, mUserId);
                res = result.result;
            } else {
                res = mAm.startActivityAsUser(null, null, intent, mimeType,
                        null, null, 0, mStartFlags, profilerInfo,
                        options != null ? options.toBundle() : null, mUserId);
            }
            final long endTime = SystemClock.uptimeMillis();
			   if (result == null) {
                    result = new IActivityManager.WaitResult();
                    result.who = intent.getComponent();
                }
                System.out.println("Status: " + (result.timeout ? "timeout" : "ok"));
                if (result.who != null) {
                    System.out.println("Activity: " + result.who.flattenToShortString());
                }
                if (result.thisTime >= 0) {
                    System.out.println("ThisTime: " + result.thisTime);
                }
                if (result.totalTime >= 0) {
                    System.out.println("TotalTime: " + result.totalTime);
                }
                System.out.println("WaitTime: " + (endTime-startTime));
                System.out.println("Complete");

在这个初始化时就已经进行了时间的计算:

frameworks\base\services\core\java\com\android\server\am\ActivityRecord.java 文件中计算
void windowsDrawnLocked() --->reportLaunchTimeLocked(SystemClock.uptimeMillis())
中完成时间的统计;
  private void reportLaunchTimeLocked(final long curTime) {
        final ActivityStack stack = task.stack;
        if (stack == null) {
            return;
        }
        final long thisTime = curTime - displayStartTime;
        final long totalTime = stack.mLaunchStartTime != 0
                ? (curTime - stack.mLaunchStartTime) : thisTime;
        if (SHOW_ACTIVITY_START_TIME) {
            Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
            EventLog.writeEvent(EventLogTags.AM_ACTIVITY_LAUNCH_TIME,
                    userId, System.identityHashCode(this), shortComponentName,
                    thisTime, totalTime);
            StringBuilder sb = service.mStringBuilder;
            sb.setLength(0);
            sb.append("Displayed ");
            sb.append(shortComponentName);
            sb.append(": ");
            TimeUtils.formatDuration(thisTime, sb);
            if (thisTime != totalTime) {
                sb.append(" (total ");
                TimeUtils.formatDuration(totalTime, sb);
                sb.append(")");
            }
            Log.i(TAG, sb.toString());
        }
        mStackSupervisor.reportActivityLaunchedLocked(false, this, thisTime, totalTime);
        if (totalTime > 0) {
            //service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
        }
        displayStartTime = 0;
        stack.mLaunchStartTime = 0;
    }

6 Trace工具分析代码执行时间

Debug.startMethodTracing(filePath);
//中间为需要统计执行时间的代码
Debug.stopMethodTracing();
adb pull /storage/emulated/0/app1.trace 把文件拉出来分析

把pull到电脑上的文件拖到AS中就可以分析了

效果如下图:
Android APP启动优化_第5张图片
Android APP启动优化_第6张图片

Android APP启动优化_第7张图片

优化方案:
1.开线程 没建handler 没操作UI 对异步要求不高
2.懒加载 用到的时候再初始化,如网络,数据库操作

public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        File file = new File(Environment.getExternalStorageDirectory(), "app1.trace");
        Log.i(TAG, "onCreate: " + file.getAbsolutePath());
        //把分析结果存在一个文件
        Debug.startMethodTracing(file.getAbsolutePath());
        //对全局属性赋值
        mContext = getApplicationContext();
        mMainThread = Thread.currentThread();
        mMainThreadId = android.os.Process.myTid();
        mMainLooper = getMainLooper();
        mHandler = new Handler();
        //因为LQRUIKit中已经对ImageLoader进行过初始化了
		//initImageLoader(getApplicationContext());
        new Thread(){
            @Override
            public void run() {
                //如果要用线程来节约了这些初始化的时间
                //1.里面的API不能去创建handler
                //2.不能有UI操作
                //3.对异步要求不高
                initNim();
                initImagePicker();
                initOkHttp();//可以懒加载
            }
        }.start();
        initNim();
        initImagePicker();
        initOkHttp();//可以懒加载

        NIMClient.init(this, loginInfo(), options());
        Debug.stopMethodTracing();
    }

	...

}

你可能感兴趣的:(Android性能优化)