分析Android Activity的启动过程

分析Android Activity的启动过程,第1张

概述分析AndroidActivity的启动过程         对于AndroidActivity的启动过程,我在Android源码中读了好久的源码,以下是我整理出来的Activity启动过程和大家分享下:

分析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,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,options);    } else {     mParent.startActivityFromChild(this,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,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.resolveTypeIfNeeded(who.getContentResolver()),token,target != null ? target.mEmbeddedID : 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,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 @R_563_4404@_ACTIVITY: {    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"activityRestart");    ActivityClIEntRecord r = (ActivityClIEntRecord)msg.obj;    handle@R_563_4404@Activity(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,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,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,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.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.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的稍微简单一些,这里就不再详细叙述了,各位可以自行根据前面步骤,阅读源代码。

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

总结

以上是内存溢出为你收集整理的分析Android Activity的启动过程全部内容,希望文章能够帮你解决分析Android Activity的启动过程所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1145679.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存