美文网首页Android开发Android开发经验谈Android技术知识
开发12年Android,整理这个居然让怀疑我是不是做了个假An

开发12年Android,整理这个居然让怀疑我是不是做了个假An

作者: jett老师 | 来源:发表于2020-06-29 10:25 被阅读0次

前言

应用启动流程简单分为三个模块,其中最后由ActivityThread启动Activity是常见的面试高频问题,所以前面两个部分简单整理(有空再上源码分析),第三部分从源码分析,讲的比较详细。

一.Launcher请求ActivityManageService

1.点击图标,调用 launcher类 的 startActivitySafely 方法,其中调用了内部方法 startActivity,
2.方法里设置了 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);这样根Activity会在新的任务栈中启动,然后调用了activity的 startActivity方法
3.startActivity 又调用 startActivityForResult 方法
4.startActivityForResult 中判断mParent 是否为空 ,因为是根Activity还没创建,所以会走为空的分支 ,调用 Instrumentation的 execStartActivity 方法(不为空 走startActivityFromChild 方法 这个方法最终还是调用 Instrumentation的 execStartActivity 方法 具体情况后续分析)
5.看到 nstrumentation的 execStartActivity 方法 ,首先会调用ActivityManagerNative的getDefault来获取ActivityManageService(以后简称为AMS)的代理对象(AMP),接着调用它的startActivity方法。
6.AMP是 ActivityManagerNative 的内部类 ,startActivity方法,通过IBinder对象mRemote向AMS发送一个START_ACTIVITY_TRANSACTION类型的进程间通信请求。那么服务端AMS就会从Binder线程池中读取我们客户端发来的数据,最终会调用ActivityManagerNative的onTransact方法中执行,
7.onTransact中会调用AMS的startActivity方法


二.ActivityManageService到ApplicationThread的调用流程

1.AMS的startActivity方法中return了startActivityAsUser方法:
2.startActivityAsUser方法中又return了mActivityStarter的startActivityMayWait方法
3.又调用了startActivityLocked方法
4.接着又调用startActivityUnchecked方法:
5.startActivityUnchecked方法中调用了ActivityStackSupervisor类型的mSupervisor的resumeFocusedStackTopActivityLocked方法
6.在注释1处又调用了ActivityStack类型mFocusedStack的resumeTopActivityUncheckedLocked方法:
7.紧接着查看ActivityStack的resumeTopActivityInnerLocked方法
8.最后运行 realStartActivityLocked方法 ,app.thread指的是IApplicationThread,它的实现是ActivityThread的内部类ApplicationThread,其中ApplicationThread继承了ApplicationThreadNative,而ApplicationThreadNative继承了Binder并实现了IApplicationThread接口。最后调用了ApplicationThread的scheduleLaunchActivity方法

三.ActivityThread启动Activity(重点来了)

ApplicationThread的scheduleLaunchActivity方法,scheduleLaunchActivity方法会将启动Activity的参数封装成ActivityClientRecord,调用sendMessage传递参数

frameworks/base/core/java/android/app/ActivityThread.java:

@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
        ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
        CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
        int procState, Bundle state, PersistableBundle persistentState,
        List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
        boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
 updateProcessState(procState, false);
    ActivityClientRecord r = new ActivityClientRecord();
    r.token = token;
    r.ident = ident;
    r.intent = intent;
    r.referrer = referrer;
    r.voiceInteractor = voiceInteractor;
    r.activityInfo = info;
    r.compatInfo = compatInfo;
    r.state = state;
    r.persistentState = persistentState;
    r.pendingResults = pendingResults;
    r.pendingIntents = pendingNewIntents;
    r.startsNotResumed = notResumed;
    r.isForward = isForward;
    r.profilerInfo = profilerInfo;
    r.overrideConfig = overrideConfig;
    updatePendingConfiguration(curConfig);
    sendMessage(H.LAUNCH_ACTIVITY, r);//传递参数
}

sendMessage方法向H类发送类型为LAUNCH_ACTIVITY的消息,并将ActivityClientRecord 传递过去,

frameworks/base/core/java/android/app/ActivityThread.java:

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
   ...
      mH.sendMessage(msg);
  }

这里mH指的是H,它是ActivityThread的内部类并继承Handler,H的代码如下所示。
frameworks/base/core/java/android/app/ActivityThread.java

private class H extends Handler {
      public static final int LAUNCH_ACTIVITY         = 100;
      public static final int PAUSE_ACTIVITY          = 101;
...
public void handleMessage(Message msg) {
          if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
          switch (msg.what) {
              case LAUNCH_ACTIVITY: {
                  Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                  final ActivityClientRecord r = (ActivityClientRecord) msg.obj;//1
                  r.packageInfo = getPackageInfoNoCheck(
                          r.activityInfo.applicationInfo, r.compatInfo);//2
                  handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");//3
                  Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
              } break;
              case RELAUNCH_ACTIVITY: {
                  Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
                  ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                  handleRelaunchActivity(r);
                  Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
              } break;
            ...

查看H的handleMessage方法中对LAUNCH_ACTIVITY的处理,在注释1处将传过来的msg的成员变量obj转换为ActivityClientRecord。
在注释2处通过getPackageInfoNoCheck方法获得LoadedApk类型的对象并赋值给ActivityClientRecord 的成员变量packageInfo 。应用程序进程要启动Activity时需要将该Activity所属的APK加载进来,而LoadedApk就是用来描述已加载的APK文件。
在注释3处调用handleLaunchActivity方法,代码如下所示。

frameworks/base/core/java/android/app/ActivityThread.java

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ...
      Activity a = performLaunchActivity(r, customIntent);//1
      if (a != null) {
          r.createdConfig = new Configuration(mConfiguration);
          reportSizeConfigurations(r);
          Bundle oldState = r.state;
          handleResumeActivity(r.token, false, r.isForward,
                  !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);//2

          if (!r.activity.mFinished && r.startsNotResumed) {      
              performPauseActivityIfNeeded(r, reason);
              if (r.isPreHoneycomb()) {
                  r.state = oldState;
              }
          }
      } else {
          try {
              ActivityManagerNative.getDefault()
                  .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                          Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
          } catch (RemoteException ex) {
              throw ex.rethrowFromSystemServer();
          }
      }
  }

注释1处的performLaunchActivity方法用来启动Activity ,注释2处的代码用来将Activity 的状态置为Resume。如果该Activity为null则会通知ActivityManager停止启动Activity。来查看performLaunchActivity方法做了什么:

frameworks/base/core/java/android/app/ActivityThread.java

  private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
  ...
        ActivityInfo aInfo = r.activityInfo;//1获取ActivityInfo
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);//2获取APK文件的描述类LoadedApk
        }
        ComponentName component = r.intent.getComponent();//3获取要启动的Activity的ComponentName类
      ...
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);//4用类加载器来创建该Activity的实例
           ...
            }
        } catch (Exception e) {
         ...
        }
        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);//5创建Application

        ...
            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);//6创建要启动Activity的上下文环境
         ...
                }
                /**
                *7用Activity的attach方法初始化Activity
                */
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window);

              ...
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);//8调用Instrumentation的callActivityOnCreate方法来启动Activity
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                ...
        }
        return activity;
}

注释1处用来获取ActivityInfo,在注释2处获取APK文件的描述类LoadedApk。注释3处获取要启动的Activity的ComponentName类,ComponentName类中保存了该Activity的包名和类名。注释4处根据ComponentName中存储的Activity类名,用类加载器来创建该Activity的实例。注释5处用来创建Application,makeApplication方法内部会调用Application的onCreate方法。注释6处用来创建要启动Activity的上下文环境。注释7处调用Activity的attach方法初始化Activity,attach方法中会创建Window对象(PhoneWindow)并与Activity自身进行关联。注释8处会调用Instrumentation的callActivityOnCreate方法来启动Activity:

frameworks/base/core/java/android/app/Instrumentation.java

public void callActivityOnCreate(Activity activity, Bundle icicle,
         PersistableBundle persistentState) {
     prePerformCreate(activity);
     activity.performCreate(icicle, persistentState);//1
     postPerformCreate(activity);
 }

注释1处调用了Activity的performCreate方法,代码如下所示。

frameworks/base/core/java/android/app/Activity.java

final void performCreate(Bundle icicle) {
      restoreHasCurrentPermissionRequest(icicle);
      onCreate(icicle);
      mActivityTransitionState.readState(icicle);
      performCreateCommon();
  }

performCreate方法中会调用Activity的onCreate方法,这样Activity就启动了,即应用程序就启动了。


有想学习Android的程序员,或者是想进阶提升的成为Android高级架构师的程序员都可以点击【Android高级工程师进阶学习】加入我们的圈子领取资料和我们一起吧学习交流!下面是我在开发12年以来,整理搜集的一些资料,不多但是好在比较系统有需要的朋友,可以自行领取!
  • Android进阶学习全套手册
    关于实战,我想每一个做开发的都有话要说,对于小白而言,缺乏实战经验是通病,那么除了在实际工作过程当中,我们如何去更了解实战方面的内容呢?实际上,我们很有必要去看一些实战相关的电子书。目前,我手头上整理到的电子书还算比较全面,HTTP、自定义view、c++、MVP、Android源码设计模式、Android开发艺术探索、Java并发编程的艺术、Android基于Glide的二次封装、Android内存优化——常见内存泄露及优化方案、.Java编程思想 (第4版)等高级技术都囊括其中。
  • Android高级架构师进阶知识体系图
    关于视频这块,我也是自己搜集了一些,都按照Android学习路线做了一个分类。按照Android学习路线一共有八个模块,其中视频都有对应,就是为了帮助大家系统的学习。接下来看一下导图和对应系统视频吧!!!

  • Android对标阿里P7学习视频

  • BATJ大厂Android高频面试题
    这个题库内容是比较多的,除了一些流行的热门技术面试题,如Kotlin,数据库,Java虚拟机面试题,数组,Framework ,混合跨平台开发,等

相关文章

  • 开发12年Android,整理这个居然让怀疑我是不是做了个假An

    前言 应用启动流程简单分为三个模块,其中最后由ActivityThread启动Activity是常见的面试高频问题...

  • 2021-05-10

    婆婆正式上岗在家的第一天。早上起来帮我做了早饭,煎了馒头鸡蛋,让我一度怀疑她是不是个假护士,哈哈。晚上回来,水果已...

  • 何等面试题!竟将6年的 Android 高工击倒?

    前几天我朋友跟我吐苦水,这波面试又把他打击到了,做了快6年Android开发。。。 因此整理这份Android面试...

  • 佳节相聚

    国庆长假,假期尾巴恰逢重阳,很多相聚的由头。但发现我的手机里居然没有一张和国庆有关的图片,怀疑自己是不是过了一个假...

  • 夜间的梦

    那是一个神奇的梦。 夜里的我,居然梦到一个孩子向我求婚…… 半跪的姿势……忠诚的言语…… 一度让我怀疑这是真是假…...

  • 快速开发框架与工具类

    开发框架:XdroidXdroidMVP一个共享的开发框架Android 能让你少走弯路的干货整理Android混...

  • 我怀疑我是个假90后

    我怀疑我是个假90后,因为我目标感太弱。 我怀疑我是个假90后,因为我总是彷徨犹豫。 我怀疑我是个假90够,因为我...

  • 无戒学堂7天学习心得

    我是猿妞儿,起这个名字是因为我是一名程序员,做过Android-APP开发,后来做了前端开发。可是做软件开发这个行...

  • 136.努力找到自己的优势

    努力找到自己的优势 人生大事始终未定让人时不时怀疑人生,甚至怀疑朋友的意义,怀疑是不是上辈子做了什...

  • 我做了个假兼职

    上班的人都有一个挣钱的梦想,我总觉得给我一个支点我就能挣到一个亿,单位离开我就运转不了了,创造出来的价值全都被老板...

网友评论

    本文标题:开发12年Android,整理这个居然让怀疑我是不是做了个假An

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