欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

分析Android Activity的启动过程

程序员文章站 2022-10-29 15:00:02
分析android activity的启动过程           对于andr...

分析android activity的启动过程

          对于android activity 的启动过程,我在android源码中读了好久的源码,以下是我整理出来的activity启动过程和大家分享下:

activity作为android的四大组件之一,也是最基本的组件,负责与用户交互的所有功能。activity的启动过程也并非一件神秘的事情,接下来就简单的从源码的角度分析一下activity的启动过程。

根activity一般就是指我们项目中的mainactivity,代表了一个android应用程序,一般也是在一个新的进程中启动起来。在android系统中,所有的activity组件都保存在堆栈中,我们启动一个新的activity组件就位于上一个activity的上面。那么我们从桌面(launcher)打开一个app是一个怎样的过程呢,如下所示:

    (1)launcher向activitymanagerservice发送一个启动mainactivity的请求;
    (2)activitymanagerservice首先将mainactivity的相关信息保存下来,然后向launcher发送一个使之进入中止状态的请求;
    (3)launcher收到中止状态之后,就会想activitymanagerservice发送一个已进入中止状态的请求,便于activitymanagerservice继续执行启动mainactivity的操作;
    (4)activitymanagerservice检查用于运行mainactivity的进程,如果不存在,则启动一个新的进程;
    (5)新的应用程序进程启动完成之后,就会向activitymanagerservice发送一个启动完成的请求,便于activitymanagerservice继续执行启动mainactivity的操作;
    (6)activitymanagerservice将第(2)步保存下来的mainactivity相关信息发送给新创建的进程,便于该进程启动mainactivity组件。

launcher.startactivitysafely

boolean startactivitysafely(intent intent, object tag) { 
  intent.addflags(intent.flag_activity_new_task); 
  try { 
   startactivity(intent); 
   return true; 
  } catch (activitynotfoundexception e) {} 
} 

当我们在launcher上点击应用程序图标时,startactivitysafely方法会被调用。需要启动的activity信息保存在intent中,包括action、category等等。那么launcher是如何获得intent里面的这些信息呢?首先,系统在启动时会启动一个叫做packagemanagerservice的管理服务,并且通过他来安装系统中的应用程序,在这个过程中,packagemanagerservice会对应用程序的配置文件androidmanifest.xml进行解析,从而得到程序里的组件信息(包括activity、service、broadcast等),然后packagemanagerservice去查询所有action为“android.intent.action.main”并且category为“android.intent.category.launcher”的activity,然后为每个应用程序创建一个快捷方式图标,并把程序信息与之关联。上述代码中,activity的启动标志位设置为“intent.flag_activity_new_task”,便于他可以在一个新的任务中启动。

activity.startactivity

@override 
 public void startactivity(intent intent, @nullable bundle options) { 
  if (options != null) { 
   startactivityforresult(intent, -1, options); 
  } else { 
   startactivityforresult(intent, -1); 
  } 
 } 

调用startactivityforresult,第二个参数(requestcode)为-1则表示在activity关闭时不需要将结果传回来。

activity.startactivityforresult

public void startactivityforresult(intent intent, int requestcode, @nullable bundle options) { 
  if (mparent == null) { //一般的activity其mparent都为null 
   instrumentation.activityresult ar = minstrumentation.execstartactivity(this, 
      mmainthread.getapplicationthread(), mtoken, this,intent, requestcode, options); 
   if (ar != null) { //发送结果,即onactivityresult会被调用 
    mmainthread.sendactivityresult(mtoken, membeddedid, requestcode, ar.getresultcode(), 
      ar.getresultdata()); 
   } 
   if (requestcode >= 0) { 
    mstartedactivity = true; 
   } 
 
   final view decor = mwindow != null ? mwindow.peekdecorview() : null; 
   if (decor != null) { 
    decor.cancelpendinginputevents(); 
   } 
  } else { //在activitygroup内部的activity,内部处理逻辑和上面是类似的 
   if (options != null) { 
    mparent.startactivityfromchild(this, intent, requestcode, options); 
   } else { 
    mparent.startactivityfromchild(this, intent, requestcode); 
   } 
  } 
  if (options != null && !istopoftask()) { 
   mactivitytransitionstate.startexitouttransition(this, options); 
  } 
 } 

不难发现,最后实际上是调用minstrumentation.execstartactivity来启动activity,minstrumentation类型为instrumentation,用于监控程序和系统之间的交互操作。minstrumentation代为执行activity的启动操作,便于他可以监控这一个交互过程。

mmainthread的类型为activitythread,用于描述一个应用程序进程,系统每启动一个程序都会在它里面加载一个activitythread的实例,并且将该实例保存在activity的成员变量mmainthread中,而mmainthread.getapplicationthread()则用于获取其内部一个类型为applicationthread的本地binder对象。mtoken的类型为ibinder,他是一个binder的代理对象,只想了activitymanagerservice中一个类型为activityrecord的本地binder对象。每一个已经启动的activity在activitymanagerservice中都有一个对应的activityrecord对象,用于维护activity的运行状态及信息。

instrumentation.execstartactivity

public activityresult execstartactivity(context who, ibinder contextthread, ibinder token, activity target, 
   intent intent, int requestcode, bundle options) { 
  iapplicationthread whothread = (iapplicationthread) contextthread; 
  if (mactivitymonitors != null) { 
   synchronized (msync) { 
    final int n = mactivitymonitors.size(); 
    for (int i=0; i<n; i++) { //先查找一遍看是否存在这个activity 
     final activitymonitor am = mactivitymonitors.get(i); 
     if (am.match(who, null, intent)) { 
      am.mhits++; 
      if (am.isblocking()) { 
       return requestcode >= 0 ? am.getresult() : null; 
      } 
      break; 
     } 
    } 
   } 
  } 
  try { 
   intent.migrateextrastreamtoclipdata(); 
   intent.preparetoleaveprocess(); 
   int result = activitymanagernative.getdefault().startactivity(whothread, who.getbasepackagename(), intent, 
      intent.resolvetypeifneeded(who.getcontentresolver()),token, target != null ? target.membeddedid : null, 
      requestcode, 0, null, options); //这里才是真正打开activity的地方,其核心功能在whothread中完成。 
   checkstartactivityresult(result, intent); // 处理各种异常,如activitynotfound 
  } catch (remoteexception e) { 
  } 
  return null; 
 } 

上述代码可知,通过activitymanagernative.getdefault()获取一个activitymanagerservice的代理对象,然后调用他的startactivity方法来通知activitymanagerservice去启动activity。

中间还有一系列过程,跟着源码走下去,不难发现,最后,是调用applicationthread的schedulelaunchactivity来进行activity的启动。

application.schedulelaunchactivity

public final void schedulelaunchactivity(intent intent, ibinder token, int ident, 
    activityinfo info, configuration curconfig, 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; 
 
   updatependingconfiguration(curconfig); 
 
   sendmessage(h.launch_activity, r); 
  } 

上述代码主要做的事就是构造一个activityclientrecord,然后调用sendmessage发送一个消息。在应用程序对应的进程中,每一个activity组件都使用一个activityclientrecord对象来描述,他们保存在activitythread类的成员变量mactivities中。那么handler是如何处理这个消息的呢?

h.handlemessage

switch (msg.what) { // 消息类型 
  case launch_activity: { 
   trace.tracebegin(trace.trace_tag_activity_manager, "activitystart"); 
   final activityclientrecord r = (activityclientrecord) msg.obj; 
 
   r.packageinfo = getpackageinfonocheck( 
     r.activityinfo.applicationinfo, r.compatinfo); 
   handlelaunchactivity(r, null); // 处理消息 
   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; 
  case pause_activity: 
   trace.tracebegin(trace.trace_tag_activity_manager, "activitypause"); 
   handlepauseactivity((ibinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2, 
     (msg.arg1&2) != 0); 
   maybesnapshot(); 
   trace.traceend(trace.trace_tag_activity_manager); 
   break; 
  ... ... 
} 

首先将msg里面的obj转成一个activityclientrecord对象,然后调用来获取一个loaderapk对象并保存在activityclientrecord对象的成员变量packageinfo中。loader对象用于描述一个已经加载的apk文件。最后调用handlelaunchactivity来启动activity组件。

activitythread.handlelaunchactivity

private void handlelaunchactivity(activityclientrecord r, intent customintent) { 
  unschedulegcidler(); 
  msomeactivitieschanged = true; 
 
  if (r.profilerinfo != null) { 
   mprofiler.setprofiler(r.profilerinfo); 
   mprofiler.startprofiling(); 
  } 
 
  handleconfigurationchanged(null, null); 
 
  if (locallogv) slog.v( 
   tag, "handling launch of " + r); 
 
  windowmanagerglobal.initialize(); 
 
  activity a = performlaunchactivity(r, customintent); //performlaunchactivity真正完成了activity的调起,activity被实例化,oncreate被调用 
 
  if (a != null) { 
   r.createdconfig = new configuration(mconfiguration); 
   bundle oldstate = r.state; 
   handleresumeactivity(r.token, false, r.isforward, // 再调用activity实例的resume(用户界面可见) 
     !r.activity.mfinished && !r.startsnotresumed); 
 
   if (!r.activity.mfinished && r.startsnotresumed) { 
    try { 
     r.activity.mcalled = false; 
     minstrumentation.callactivityonpause(r.activity); // finish的时候先调onpause 
     if (r.isprehoneycomb()) { 
      r.state = oldstate; 
     } 
     if (!r.activity.mcalled) { 
      throw new supernotcalledexception( 
       "activity " + r.intent.getcomponent().toshortstring() + 
       " did not call through to super.onpause()"); 
     } 
 
    } catch (supernotcalledexception e) { 
     throw e; 
 
    } catch (exception e) { 
     if (!minstrumentation.onexception(r.activity, e)) { 
      throw new runtimeexception( 
        "unable to pause activity " 
        + r.intent.getcomponent().toshortstring() 
        + ": " + e.tostring(), e); 
     } 
    } 
    r.paused = true; 
   } 
  } else { 
   try { 
    activitymanagernative.getdefault() // finishactivity 一样的原理 
     .finishactivity(r.token, activity.result_canceled, null, false); 
   } catch (remoteexception ex) { 
   } 
  } 
 } 

到了这一步,那就很清晰了。憋了一口气到这里,是不是突然放松了一下~~  再来看看performlaunchactivity做的事儿~~performlaunchactivity函数加载用户自定义的activity的派生类,并执行其oncreate函数,它将返回此activity对象。

activitythread.performlaunchactivity

private activity performlaunchactivity(activityclientrecord r, intent customintent) { 
  activityinfo ainfo = r.activityinfo; 
  if (r.packageinfo == null) { 
   r.packageinfo = getpackageinfo(ainfo.applicationinfo, r.compatinfo, 
     context.context_include_code); 
  } 
  //从intent中取出目标activity的启动参数(包名、类名等) 
  componentname component = r.intent.getcomponent(); 
  if (component == null) { 
   component = r.intent.resolveactivity( 
    minitialapplication.getpackagemanager()); 
   r.intent.setcomponent(component); 
  } 
 
  if (r.activityinfo.targetactivity != null) { 
   component = new componentname(r.activityinfo.packagename, 
     r.activityinfo.targetactivity); 
  } 
 
  activity activity = null; 
  try { 
   java.lang.classloader cl = r.packageinfo.getclassloader(); // 将activity类文件加载到内存中 
   activity = minstrumentation.newactivity( // 创建activity实例 
     cl, component.getclassname(), r.intent); 
   strictmode.incrementexpectedactivitycount(activity.getclass()); 
   r.intent.setextrasclassloader(cl); 
   r.intent.preparetoenterprocess(); 
   if (r.state != null) { 
    r.state.setclassloader(cl); 
   } 
  } catch (exception e) { 
   if (!minstrumentation.onexception(activity, e)) { 
    throw new runtimeexception( 
     "unable to instantiate activity " + component 
     + ": " + e.tostring(), e); 
   } 
  } 
 
  try { 
   application app = r.packageinfo.makeapplication(false, minstrumentation); 
 
   if (locallogv) slog.v(tag, "performing launch of " + r); 
   if (locallogv) slog.v( 
     tag, r + ": app=" + app 
     + ", appname=" + app.getpackagename() 
     + ", pkg=" + r.packageinfo.getpackagename() 
     + ", comp=" + r.intent.getcomponent().toshortstring() 
     + ", dir=" + r.packageinfo.getappdir()); 
 
   if (activity != null) { 
    context appcontext = createbasecontextforactivity(r, activity); // 初始化context对象,作为activity的上下文 
    charsequence title = r.activityinfo.loadlabel(appcontext.getpackagemanager()); 
    configuration config = new configuration(mcompatconfiguration); 
    if (debug_configuration) slog.v(tag, "launching activity " 
      + r.activityinfo.name + " with config " + config); 
    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); 
 
    if (customintent != null) { 
     activity.mintent = customintent; 
    } 
    r.lastnonconfigurationinstances = null; 
    activity.mstartedactivity = false; 
    int theme = r.activityinfo.getthemeresource(); 
    if (theme != 0) { 
     activity.settheme(theme); 
    } 
 
    activity.mcalled = false; 
    if (r.ispersistable()) { //下面就是调用到acitivity的oncreate方法了 
     minstrumentation.callactivityoncreate(activity, r.state, r.persistentstate); 
    } else { 
     minstrumentation.callactivityoncreate(activity, r.state); 
    } // 至此,activity启动过程就结束了,其生命周期由applicationthread来管理 
    if (!activity.mcalled) { 
     throw new supernotcalledexception( 
      "activity " + r.intent.getcomponent().toshortstring() + 
      " did not call through to super.oncreate()"); 
    } 
    r.activity = activity; 
    r.stopped = true; 
    if (!r.activity.mfinished) { 
     activity.performstart(); 
     r.stopped = false; 
    } 
    if (!r.activity.mfinished) { 
     if (r.ispersistable()) { 
      if (r.state != null || r.persistentstate != null) { 
       minstrumentation.callactivityonrestoreinstancestate(activity, r.state, 
         r.persistentstate); 
      } 
     } else if (r.state != null) { 
      minstrumentation.callactivityonrestoreinstancestate(activity, r.state); 
     } 
    } 
    if (!r.activity.mfinished) { 
     activity.mcalled = false; 
     if (r.ispersistable()) { 
      minstrumentation.callactivityonpostcreate(activity, r.state, 
        r.persistentstate); 
     } else { 
      minstrumentation.callactivityonpostcreate(activity, r.state); 
     } 
     if (!activity.mcalled) { 
      throw new supernotcalledexception( 
       "activity " + r.intent.getcomponent().toshortstring() + 
       " did not call through to super.onpostcreate()"); 
     } 
    } 
   } 
   r.paused = true; 
   mactivities.put(r.token, r); // 将activityrecord对象保存在activitythread的mactivities中 
  } catch (supernotcalledexception e) { 
   throw e; 
  } catch (exception e) { 
   if (!minstrumentation.onexception(activity, e)) { 
    throw new runtimeexception( 
     "unable to start activity " + component 
     + ": " + e.tostring(), e); 
   } 
  } 
  return activity; 
 } 

activityrecord里面的token,是一个binder的代理对象,和activityclientrecord对象一样,都是用来描述所启动的activity组件,只不过前者是在activitymanagerservice中使用,后者是在应用程序进程中使用。

至此,activity的启动过程就分析完了。mainactivity的启动过程,其实也可以认为是应用程序的启动过程。
子activity的启动过程和根activity的启动过程也是类似的,过程如下:

    (1)mainactivity向activitymanagerservice发送一个自动childactivity的请求;

    (2)activitymanagerservice首先将childactivity的信息保存下来,再向mainactivity发送一个中止的请求;

    (3)mainactivity收到请求进入中止状态,告诉activitymanagerservice,便于activitymanagerservice继续执行启动childactivity的操作

    (4)activitymanagerservice检查childactivity所运行的进程是否存在,存在就发送childactivity信息给他,以进行启动。
源代码方面,原理类似,相比起来会比mainactivity的稍微简单一些,这里就不再详细叙述了,各位可以自行根据前面步骤,阅读源代码。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!