Android Activity启动流程分析

发表于:2018-4-17 11:56

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:xiangzhihong8    来源:CSDN

#
流程
分享:
  概述
  Activity作为Android的四大组件之一,Android主要的界面组成部分,用于直接跟用户进行交互操作,在面试中与Activity相关的知识也是经常被问到,如果你面试的高级岗位,那么对Activity的启动和绘制流程就必须的熟悉,本文将从Activity的启动流程来分析Activity。启动Activity的方式大致有两种:一种是在桌面点击应用程序的图标,进入应用程序的主界面;另一种是在应用程序中,进入一个新的Activity。前者属于launcher启动的范畴,本文不做具体的深入分析,后面会具体的分析,不过它的实质是从一个应用的Activity进入另一个应用Activity。 
  因此,不管是从桌面进入应用主界面,还是在应用里进入一个新的Activity,最终都会调用Activity$startActivity方法。 
  值得注意的是,Android 5.0,7.0等版本中启动Activity的流程略微有一些细小的改变,但这并不妨碍我们理解Activity的启动流程。
  Binder机制
  首先,我们要介绍下Android系统中一个重要的内容:Binder机制。为了满足进程间的通信,Android系统将进程分为了用户(Zygote)进程和系统(SystemServer)进程以及各种应用进程等,为了能够实现各种进程之间的通讯,Android系统采用了自己的进程间通讯方式Binder机制。其中主要涉及到了四种角色:Binder Client,Binder Server,Binder Manager, Binder driver。各种角色之间的关系可以参考下面这张图的介绍: 
  启动Activity流程解读
  当我们使用startActivity() 启动另一个Activity后,主要会调用以下的一些函数。
  MyActivity.startActivity() 
  Activity.startActivity() 
  Activity.startActivityForResult 
  Instrumentation.execStartActivty 
  ActivityManagerNative.getDefault().startActivityAsUser() 
  首先,我们来看一下startActivity()函数的源码:
  @Override
      public void startActivity(Intent intent) {
          this.startActivity(intent, null);
      }
      @Override
      public void startActivity(Intent intent, @Nullable Bundle options) {
          if (options != null) {
              startActivityForResult(intent, -1, options);
          } else {
              startActivityForResult(intent, -1);
          }
      }
  其实,startActivity还有几个其他重载的方法,但是最终都会执行到Activity$startActivityForResult方法。如果是调用startActivity(intent)启动Activity,那么requestCode参数则传入-1,表示需要返回Activity的数据。
  到此继续往下看,startActivityForResult方法的具体实现如下:
      public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
              @Nullable Bundle options) {
          if (mParent == null) {
              Instrumentation.ActivityResult ar =
                  mInstrumentation.execStartActivity(
                      this, mMainThread.getApplicationThread(), mToken, this,
                      intent, requestCode, options);
              if (ar != null) {
                  mMainThread.sendActivityResult(
                      mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                      ar.getResultData());
              }
              if (requestCode >= 0) {
                  // If this start is requesting a result, we can avoid making
                  // the activity visible until the result is received.  Setting
                  // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                  // activity hidden during this time, to avoid flickering.
                  // This can only be done when a result is requested because
                  // that guarantees we will get information back when the
                  // activity is finished, no matter what happens to it.
                  mStartedActivity = true;
              }
              cancelInputsAndStartExitTransition(options);
              // TODO Consider clearing/flushing other event sources and events for child windows.
          } else {
              if (options != null) {
                  mParent.startActivityFromChild(this, intent, requestCode, options);
              } else {
                  // Note we want to go through this method for compatibility with
                  // existing applications that may have overridden it.
                  mParent.startActivityFromChild(this, intent, requestCode);
              }
          }
      }
  在上面的代码中,mParent进行了一个判Null操作,可以发现由于我们是第一次启动Activity,所以这里的mParent为空,所以会执行if分之,然后调用mInstrumentation.execStartActivity方法,并且这里需要注意的是,有一个判断逻辑。即:
  if (requestCode >= 0) {
      mStartedActivity = true;
  }
  前面说过,调用startActivityForResult的时候只有requestCode的值大于等于0,onActivityResult才会被回调。
  Instrumentation
  然后我们看一下mInstrumentation.execStartActivity方法的具体实现。在看execStartActivity方法之前,首先看一下Instrumentation,Instrumentation是android系统中启动Activity的一个实际操作类,也就是说Activity在应用进程端的启动实际上就是Instrumentation执行的。那为什么是这样呢?实际上acitivty的启动分为应用进程端的启动和SystemServer服务进程端的启动的,多个应用进程相互配合最终完成了Activity在系统中的启动的,而在应用进程端的启动实际的操作类就是Intrumentation来执行的。
  为了方便理解,我们直接看execStartActivity函数源码:
   public ActivityResult execStartActivity(
              Context who, IBinder contextThread, IBinder token, Activity target,
              Intent intent, int requestCode, Bundle options) {
          IApplicationThread whoThread = (IApplicationThread) contextThread;
          Uri referrer = target != null ? target.onProvideReferrer() : null;
          if (referrer != null) {
              intent.putExtra(Intent.EXTRA_REFERRER, referrer);
          }
          if (mActivityMonitors != null) {
              synchronized (mSync) {
                  final int N = mActivityMonitors.size();
                  for (int i=0; i<N; i++) {
                      final ActivityMonitor am = mActivityMonitors.get(i);
                      ActivityResult result = null;
                      if (am.ignoreMatchingSpecificIntents()) {
                          result = am.onStartActivity(intent);
                      }
                      if (result != null) {
                          am.mHits++;
                          return result;
                      } else if (am.match(who, null, intent)) {
                          am.mHits++;
                          if (am.isBlocking()) {
                              return requestCode >= 0 ? am.getResult() : null;
                          }
                          break;
                      }
                  }
              }
          }
          try {
              intent.migrateExtraStreamToClipData();
              intent.prepareToLeaveProcess(who);
              int result = ActivityManager.getService()
                  .startActivity(whoThread, who.getBasePackageName(), intent,
                          intent.resolveTypeIfNeeded(who.getContentResolver()),
                          token, target != null ? target.mEmbeddedID : null,
                          requestCode, 0, null, options);
              checkStartActivityResult(result, intent);
          } catch (RemoteException e) {
              throw new RuntimeException("Failure from system", e);
          }
          return null;
      }
  如上,execStartActivity主要有以下几个参数: 
  this,为启动Activity的对象; 
  contextThread,为Binder对象,是主进程的context对象; 
  token,也是一个Binder对象,指向了服务端一个ActivityRecord对象; 
  target,为启动的Activity; 
  intent,启动的Intent对象; 
  requestCode,请求码; 
  options,参数; 
  通过,execStartActivity方法可以发现,该方法主要调用ActivityManager.getService()方法,继续查看ActivityManager$getService源码。
  /**  
   * @hide  
   */  
  public static IActivityManager getService() {
          return IActivityManagerSingleton.get();
      } 
  //继续查看  
  private static final Singleton<IActivityManager> IActivityManagerSingleton =  
          new Singleton<IActivityManager>() {  
              @Override  
              protected IActivityManager create() {  
                  final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);  
                  final IActivityManager am = IActivityManager.Stub.asInterface(b);  
                  return am;  
              }  
          };  
   //...code  
  }
  可以发现,IActivityManager.Stub.asInterface(b),那么继续看asInterface方法的实现:
  static public IActivityManager asInterface(IBinder obj) {
          if (obj == null) {
              return null;
          }
          IActivityManager in =
              (IActivityManager)obj.queryLocalInterface(descriptor);
          if (in != null) {
              return in;
          }
          return new ActivityManagerProxy(obj);
      }
  asInterface()返回一个ActivityManagerProxy对象,ActivityManagerProxy继承与IActivityManager,到了这里就引出了我们android系统中很重要的一个概念:Binder机制。
  IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE)
  如上,是获取一个关联了系统服务ActivityManagerService的Binder对象。所以,IBinder最终和ActivityManagerService形成了绑定关系。
  public class ActivityManagerService extends IActivityManager.Stub  
         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
     }

  所以,ActivityManager.getService().startActivity(…)的最终调用的是ActivityManagerService的startActivity方法。
  ActivityManagerService启动Activity
  首先来看一下,ActivityManagerService$startActivity的相关源码。
  @Override  
  public final int startActivity(IApplicationThread caller, String callingPackage,  
          Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,  
          int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {  
      return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,  
              resultWho, requestCode, startFlags, profilerInfo, bOptions,  
              UserHandle.getCallingUserId());  
  } 



上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号