美文网首页Android中高级进阶
关于Activity你必须掌握的知识(本篇基于8.0去分析)

关于Activity你必须掌握的知识(本篇基于8.0去分析)

作者: Sincerity_ | 来源:发表于2019-03-20 16:27 被阅读32次

    @[TOC]

    1. Activity启动模式以及使用场景?

    1. standard 标准模式 使用场景: 邮件,默认使用标准模式
    2. singleTop 栈顶复用 :登录页面 ,微信支付 微信回调,推送通知栏等
    3. singleTask 栈内单例模式: 主页面等重复调用的页面
    4. singleInstance 栈内单例模式 系统Launcher, 锁屏页面等,此种模式下系统会为这个模式下的Activity单独开辟一个栈
    5. 总结 singleTop ,singleTask ,singleInstance 三种模式如果应用内存在Activity的实例,就不会重新去创建Activity的实例,而是调用Activity的onNewIntent函数 从而Activity的oncreate和onstart没有被调用
    6. 关于singleInstance 必须知道的故事一: 此时有三个activity,ActivityA,ActivityB,ActivityC,除了ActivityB的启动模式为singleInstance,其他的启动模式都为默认的。在ActivityA里startActivity了一个ActivityB,在ActivityB里startActivity了一个ActivityC。照理来说在当前ActivityC页面按返回键,finish当前界面后应当回到ActivityB界面,但是页面直接回到了ActivityA
    • 分析 singleInstance模式是存在于另一个任务栈中的。也就是说ActivityA和ActivityC是处于同一个任务栈中的,ActivityB则是存在另个栈中。所以当关闭了ActivityC的时候,它自然就会去找当前任务栈存在的activity。当前的activity都关闭了之后,才会去找另一个任务栈中的activity。也就是说当在ActivityC中finish之后,会回到ActivityA的界面,在ActivityA里finish之后会回到ActivityB界面。
    1. 故事二:有两个ActivityA,ActivityB,ActivityA的启动模式为默认的,ActivityB的启动模式为singleInstance。当在ActivityA里startActivity了ActivityB,当前页面为ActivityB。按下home键。应用退到后台。此时再点击图标进入APP,按照天理来说,此时的界面应该是ActivityB,可是奇迹又出现了,当前显示的界面是ActivityA
    • 分析 这是因为当重新启动的时候,系统会先去找主栈(我是这么叫的)里的activity,也就是APP中LAUNCHER的activity所处在的栈。查看是否有存在的activity。没有的话则会重新启动LAUNCHER。
    1. 说了这么多 如果想让Activity回到我们想让它返回的地方如何做呢?
    • 解答在ActivityB定义一个全局变量,public static boolean returnActivityB;界面需要跳转的时候将returnActivityB=true;然后在ActivityA界面onstart方法里判断returnActivityB是否为true,是的话就跳转到ActivityB,同时将returnActivityB=false;这样就能解决跳转的问题了

    2. taskAffinity属性

    taskAffinity属性和Activity的启动模式息息相关, 这个属性在mainfest中设置,可以理解为taskAffinity为宿主Activity指定了存放的任务栈, taskAffinity只有和singleTask启动模式匹配使用,启动的Activity才会运行在名字和taskAffinity相同的任务栈中

    3. onSaveInstanceState()和onRestoreInstanceState()

    • Activity中出现异常关闭时候,尽管实际的Activity已经销毁,但是Android系统会记住它已经存在,系统会创建一个新的实例的Activity使用一组保存的数据来描述Activity在被销毁的状态,这组数据存储在Binder对象的键值对的集合中.

    • onSaveInstanceState 保存你的Activity状态.

       @Override
          protected void onSaveInstanceState(Bundle outState) {
              outState.putString("Activity_State","需要保存的数据");
              // 调用父类交给系统处理,这样系统能保存视图层次结构状态
              super.onSaveInstanceState(outState);
          }
      
    • onRestoreInstanceState()

       @Override
          protected void onRestoreInstanceState(Bundle savedInstanceState) {
              super.onRestoreInstanceState(savedInstanceState);
            //得到异常状态下的实例保存的数据
             String state = savedInstanceState.getString("Activity_State");
              
          }
      
    • 以上二种onSaveInstanceState()和onRestoreInstanceState()触发条件只在Activity异常情况下触发,正常情况下的Activity不会执行以上二个方法,可以自行验证. 具体使用的话如当前页面接受到另外页面传递过来的数据,而且当前页面可能存在奔溃情况, 可以用到这二个方法.

    4. onConfigurationChanged()属性屏幕旋转

    • 当系统的配置信息发生改变时,系统才会调用此方法,只有在配置文件AndroidMainfest中处理了configChanges属性,对应的设备配置,该方法才会被调用,

        <activity
                  android:configChanges="screenSize|orientation"
                  android:name=".MainActivity"
                  android:label="@string/app_name">
      
    • 当屏幕方向发生改变时,Activity会被销毁重建,如果在AndroidMainfest中添加处理屏幕方向配置信息,则Activity不会被销毁,而是调用onConfigurationChanged 方法

    • configChanges设置取值

      img
    • 当用户接入一个外接键盘时,默认软键盘会隐藏,系统会自动使用外设键盘,这个过程中Activity的销毁和隐藏执行了二次,并且onConfigurationChanged()方法不会调用,但是在配置文件中设置android:configChanges="keyboardHidden|keyboard"。当接入外设键盘或者拔出外设键盘时,调用的周期是先调用onConfigurationChanged()周期后销毁重建

      1. 分析,为何会二次销毁重建. 一次是键盘的插入当设置android:configChanges="keyboardHidden|keyboard"之后,就不会销毁重建,而是调用onConfigurationChanged()方法。

      2. 但是还有一次销毁重建一直存在. 经过测试发现,接入了外设,除了改变键盘类型的改变,触摸屏也发生改变,

      3. 总结 如果键盘类型发生改变,configChanges属性配置如下的Activity才不会销毁重建,且回调onConfigurationChanged方法:

         <activity
                    android:configChanges="keyboard|keyboardHidden|touchscreen"
                    android:name=".MainActivity"
                    android:label="@string/app_name">
        

    5. (主要)Activity 到底是如何启动的

    • 主要分为4个部分来叙述整个Activity是如何启动的
    1. 涉及的名词简介,
    2. Launcher请求AMS过程
      3.AMS到ActivityThread的调用过程,
      4.ActivityThread启动Activity的过程

    1. 涉及的类名介绍:

    • ActivityManagerServices 简称AMS 服务端对象,负责整个系统中Activity的生命周期
    • ActivityThread App的入口, 当App开启后,会调用它的main()方法开始运行,main()主要就是开启一个消息循环队列,与AMS配合完成Activity的管理工作, (ActivityThread就是UI线程或者主线程).
    • ApplicationThreadProxy 是ApplicationThread在服务器端的代理对象,负责和客户端的ApplicationThread通讯,但是在android8以后, ApplicationThreadProxyIApplicationThread 取代了,IApplicationThread实际上实现的ApplicationThread
    • instrumentation 每个应用程序只有一个instrumentation 对象每个Activity内部都有一个对改对象的引用,很多时候理解为应用程序进程管家,ActivityThread要创建或者暂停某个Activity时候,都需要instrumentation对象来进行具体操作
    • ActivityStack Activity在AMS的栈管理,用来记录已经启动的Activty的先后关系,状态信息等,通过ActivityStack决定是否需要启动新的进程.
    • ActivityRecord ActivityStack的管理对象,每个Activity在AMS对应的ActivityRecord,来记录Activity的状态以及其他管理信息,其时就是服务端的Activity对象的映像,
    • TaskRecord AMS抽象出来的一个任务概念,记录ActivityRecord的栈,一个Task包含若干个ActivityRecord,AMS用TaskRecord确保Activity启动和退出的顺序,

    2. Launcher请求AMS的过程

    • 此处省略init进程的创建,Zygote进程, SystemService,Launcher进程的创建.如果想了解的请自行查看资料和源码

    • Launcher是一个Activity, 它的作用就是创建一个桌面程序,存放日常App的入口,

      public final class Launcher extends Activity
              implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
      View.OnTouchListener {
            ... 
             Object tag = v.getTag();
              if (tag instanceof ShortcutInfo) {
                  onClickAppShortcut(v); //点击应用图标
              } else if (tag instanceof com.android.launcher3.FolderInfo) {
                  if (v instanceof FolderIcon) {
                      onClickFolderIcon(v); //点击文件夹
                  }
              } else if ((FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && v instanceof PageIndicator)||(v == mAllAppsButton && mAllAppsButton != null)) {
                  onClickAllAppsButton(v);
              } else if (tag instanceof AppInfo) {
                  startAppShortcutOrInfoActivity(v); //启动应用程序的入口
              } else if (tag instanceof com.android.launcher3.LauncherAppWidgetInfo) {
                  if (v instanceof com.android.launcher3.PendingAppWidgetHostView) {
                    //小部件
                      onClickPendingWidget((com.android.launcher3.PendingAppWidgetHostView) v);
                  }
              }
          ...
             private void startAppShortcutOrInfoActivity(View v) {
              com.android.launcher3.ItemInfo item = (com.android.launcher3.ItemInfo) v.getTag();
              Intent intent = item.getIntent();
              if (intent == null) {
                  throw new IllegalArgumentException("Input must have a valid intent");
              }
            //开始启动Activity了. 发现startActivitySafely()其实当我们点击桌面任意图标的时候都会触发这个方法
              boolean success = startActivitySafely(v, intent, item); //判断启动Activity是否成功
              getUserEventDispatcher().logAppLaunch(v, intent); // TODO for discovered apps b/35802115
      
              if (success && v instanceof BubbleTextView) {
                  mWaitingForResume = (BubbleTextView) v;
                  mWaitingForResume.setStayPressed(true);
              }
          }
            ...
      }
      

      我们继续跟踪startActivitySafely()方法,

      public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
            ...
              //根Activity会在新的任务栈中启动,标志启动一个新的activity
               intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
              try {
                  if (Utilities.ATLEAST_MARSHMALLOW
                          && (item instanceof ShortcutInfo)
                          && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
                          || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
                          && !((ShortcutInfo) item).isPromise()) {
                       //检查快捷方式 里面也会调用startActivity()方法
                      startShortcutIntentSafely(intent, optsBundle, item);
                  } else if (user == null || user.equals(Process.myUserHandle())) {
                      //启动Activity.startActivity()方法
                      startActivity(intent, optsBundle);
                  } 
                ....
          }
      

      回到Activity中查看startActivity方法

       @Override
          public void startActivity(Intent intent, @Nullable Bundle options) {
              if (options != null) {
                  startActivityForResult(intent, -1, options);
              } else {
                  // Note we want to go through this call for compatibility with
                  // applications that may have overridden the method.
                  startActivityForResult(intent, -1);
              }
          }
      

      startActivityForResult中可以看到调用了Instrumentation.execStartActivity()方法 并且得到一个Instrumentation的对象

      public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                                         @Nullable Bundle options) {
          if (mParent == null) {//mParent表示根Activity 即Launcher
              options = transferSpringboardActivityOptions(options);
              Instrumentation.ActivityResult ar =
                      mInstrumentation.execStartActivity(//监控应用程序和系统交互
                              this, mMainThread.getApplicationThread(), mToken, this,
                              intent, requestCode, opions);
      

      Instrumentation.execStartActivity方法的具体实现

      public ActivityResult execStartActivity(
                  Context who, IBinder contextThread, IBinder token, Activity target,
                  Intent intent, int requestCode, Bundle options) {
                    ...
              IApplicationThread whoThread = (IApplicationThread) contextThread;
                                try {
                  String[] resolvedTypes = new String[intents.length];
                  for (int i=0; i<intents.length; i++) {
                      intents[i].migrateExtraStreamToClipData();
                      intents[i].prepareToLeaveProcess(who);
                      resolvedTypes[i] =intents[i].resolveTypeIfNeeded
                        (who.getContentResolver());
                  }
                      // 通过Aidl的方式得到AMS在本地的代理类IActivityManager,通知AMS执行startActivities方法;
                  int result = ActivityManager.getService()
                      .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,token, options, userId);
                  checkStartActivityResult(result, intents[0]);
              } catch (RemoteException e) {
                  throw new RuntimeException("Failure from system", e);
              }
                  }
      

      ActivityManager.getService()

       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);//IBnder的类型的AMS
                           //将IBinder对象转换成IActivityManager
                          //此处用的是binder的AIDL方式得到一个转化后的IActivityManager对象,IActivityManager对象是AMS在本地的代理
                          final IActivityManager am = IActivityManager.Stub.asInterface(b);
                          return am;
                      }
                  };
      

      简单总结一下: 以下的流程完成了Launcher请求AMS的过程

      Launcher请求AMS的过程.png

    3. AMS到ActivityThread的调用过程

    AMS收到startActivity的请求之后,会按照如下的方法链进行调用

     //AMS中Activity的启动入口
        @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());
        }
    

    在这里又出现了一个新对象ActivityStackSupervisor,通过这个类可以实现对ActivityStack的部分操作

     @Override
     public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
                                             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                                             int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
            //判断调进程用者是否被隔离 如果隔离会有SecurityException异常
            enforceNotIsolatedCaller("startActivity");
            //检查调用者权限 没有权限也会有SecurityException异常
            userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                    userId, false, ALLOW_FULL_ONLY, "startActivity", null);
    
            // TODO: Switch to user app stacks here.
            return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                    resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                    profilerInfo, null, null, bOptions, false, userId, null, null,
                    "startActivityAsUser");
        }
    

    ActivityStarter类中的操作

        final int startActivityMayWait(IApplicationThread caller, int callingUid,...){
          ...
                    //这个ActivityStarter主要作用,加载Activity控制类,收集所有的逻辑来决定intent和flags转为               //Activity并且将Activity和Task以及Stack相关联
                final ActivityRecord[] outRecord = new ActivityRecord[1];
                int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                        aInfo, rInfo, voiceSession, voiceInteractor,
                        resultTo, resultWho, requestCode, callingPid,
                        callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                        options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                        inTask, reason);
          ...
        }
    
    
    int startActivityLocked(...) {
    
            if (TextUtils.isEmpty(reason)) { //启动理由reason
                throw new IllegalArgumentException("Need to specify a reason.");
            }
           ...
                //startActivity()
            mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                    callingPid, callingUid, callingPackage, realCallingPid, realCallingUid,                                startFlags,options, ignoreTargetSecurity, componentSpecified,                                             mLastStartActivityRecord,container, inTask);
            ...
            return mLastStartActivityResult;
        }
    
     private int startActivity(...){
       ...
        // 即将要启动的Activity的描述类ActivityRecord (用来记录Activty的所有信息)
           ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                    callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                    resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                    mSupervisor, container, options, sourceRecord);
         ...
            return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
                    options, inTask, outActivity);
     }
    
     private int startActivity(...) {
            int result = START_CANCELED;
            try {
                mService.mWindowManager.deferSurfaceLayout();
                result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                        startFlags, doResume, options, inTask, outActivity);
            }
       ...
            return result;
        }
    
    private int startActivityUnchecked(...) {
    ...
                    mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                            mOptions);
      ...
    }
    

    ActivityStackSupervisor # resumeFocusedStackTopActivityLocked

        boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
            if (targetStack != null && isFocusedStack(targetStack)) {
                return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
            }
            //获取要启动的Activity 并且所在栈的栈顶的不是处于停止状态的ActivityRecord
            final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
            if (r == null || r.state != RESUMED) {
                //继续执行ActivityStack # resumeTopActivityUncheckedLocked
                mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
            } else if (r.state == RESUMED) {
                // Kick off any lingering app transitions form the MoveTaskToFront operation.
                mFocusedStack.executeAppTransition(targetOptions);
            }
            return false;
        }
    

    ActivityStack # resumeTopActivityUncheckedLocked

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
            if (mStackSupervisor.inResumeTopActivity) {
                // Don't even start recursing.
                return false;
            }
            boolean result = false;
            try {
                // Protect against recursion.
                mStackSupervisor.inResumeTopActivity = true;
                //继续执行
                result = resumeTopActivityInnerLocked(prev, options);
            } finally {
                mStackSupervisor.inResumeTopActivity = false;
            }
            mStackSupervisor.checkReadyForSleepLocked();
    
            return result;
        }
    
     private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
            if (!mService.mBooting && !mService.mBooted) {
                // Not ready yet!
                return false;
            }
       ...
          mStackSupervisor.startSpecificActivityLocked(next, true, true);
         ...
     }
    

    ActivityStackSupervisor # startSpecificActivityLocked

    void startSpecificActivityLocked(ActivityRecord r,
                                         boolean andResume, boolean checkConfig) {
            // Is this activity's application already running?
            //获取即将要启动的Activity的所在的应用程序进程
          ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                    r.info.applicationInfo.uid, true);
    
            r.getStack().setLaunchTime(r);
            //判断要启动的 Activity 所在的应用程序进程如果已经运行
            if (app != null && app.thread != null) {
                try {
                    if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                            || !"android".equals(r.info.packageName)) {
                        // Don't add this if it is a platform component that is marked
                        // to run in multiple processes, because this is actually
                        // part of the framework so doesn't make sense to track as a
                        // separate apk in the process.
                        app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                                mService.mProcessStats);
                    }
                    //继续执行
                    realStartActivityLocked(r, app, andResume, checkConfig);
                    return;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting activity "
                            + r.intent.getComponent().flattenToShortString(), e);
                }
            }
    
            mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                    "activity", r.intent.getComponent(), false, false, true);
        }
    
    final boolean realStartActivityLocked(...){
      ...
         //app.thread 指的IApplicationThread它的实现是 ActivityThread 的内部类 ApplicationThread
         // 段代码指的就是要在目标应用程序进程启动 Activity
         //app指的是传入的要启动的Activity所在的应用程序进程 代码只要目的就是要在目标引用程序启动Activity
         //当前代码运行在AMS所在的基础进程(SystemServer进程)中,通过ApplicationThread来与应用程序进行BInder         通信,所以ApplicationThread就是AMS和应用程序通信的桥梁
         app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                        System.identityHashCode(r), r.info,
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                        r.persistentState, results, newIntents, !andResume,
                        mService.isNextTransitionForward(), profilerInfo);
        ...
    }
    

    看一下时序图再说 源码来回切换有点乱

    AMS调用ActivityThread过程.png

    4. ActivityThread启动Activity的过程

    ​ ActivityThread通过BInder接收到AMS发送过来的启动Activity的启动通知调用ApplicationThread的scheduleLaunchActivity方法 因为AMS启动Activity的时候用的 app.thread.scheduleLaunchActivityapp.thread是调用ProcessRecord.IApplicationThread对象,ApplicationThread继承于IApplicationThread.stub 所以执行ActivityThread#ApplicationThread#scheduleLaunchActivity方法

      private class ApplicationThread extends IApplicationThread.Stub {
        ...
            @Override
          public final void scheduleLaunchActivity(){
          ...
            //得到Binder传递过来的消息封装到ActivityClientRecord对象中发送给H H是一个消息进程管理类
           sendMessage(H.LAUNCH_ACTIVITY, r);
        }
          ...
      }
    

    ActivityThread#H #handleMessage

     public void handleMessage(Message msg) {
                switch (msg.what) {
                    case LAUNCH_ACTIVITY: {
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                        //将ApplicationThread传递过来的参数转换成ActivityClientRecode对象
                        final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                        //应用程序进程需要启动Activity时需要将改Activity所属的APK加载进来
                        //而 r.packageInfo返回一个loadedAPk,loadedAPk就是用来描述已加载APK文件的
                        r.packageInfo = getPackageInfoNoCheck(
                                r.activityInfo.applicationInfo, r.compatInfo);
                        //继续执行
                        handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    }
                }
     }
    
        private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {         ....
          //初始化WindowManager
            WindowManagerGlobal.initialize();
            //启动Activity
            Activity a = performLaunchActivity(r, customIntent);
    
            if (a != null) {
                r.createdConfig = new Configuration(mConfiguration);
                reportSizeConfigurations(r);
                Bundle oldState = r.state;
                //将Activity的状态设置为Resume
                handleResumeActivity(r.token, false, r.isForward,
                        !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
    
                if (!r.activity.mFinished && r.startsNotResumed) {
                    //去执行将Activity状态设置为Resume
                    performPauseActivityIfNeeded(r, reason);
                    if (r.isPreHoneycomb()) {
                        r.state = oldState;
                    }
                }
            } else {
               //如果出现错误通知AMS关闭当前Activity
                try {
                    ActivityManager.getService()
                            .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                    Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
        }
    
     private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
       ...
           appContext.setOuterContext(activity);
                    //初始化Activity activity.attach方法中会创建Window对象并且与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, r.configCallback);
         ...
             //Instrumentation.callActivityOnCreate来启动Activity 继续执行
                        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
       ....
     }
    

    Instrumentation#callActivityOnCreate

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

    Activity#performCreate

      final void performCreate(Bundle icicle) {
        //释放启动Activity过程中需要的权限
            restoreHasCurrentPermissionRequest(icicle);
            //调用Activity的onCreate方法 ,根Activity就启动完毕 
            onCreate(icicle);
            mActivityTransitionState.readState(icicle);
            performCreateCommon();
        }
    

    终于一个完成的Activity到此就启动完成了...看一下时序图吧 -眼睛都疼....

    ActivityThread启动Activity的过程.png

    上面这些调用过程非常复杂,源码中各种条件判断让人眼花缭乱,所以说如果你没记住也没关系,你只要记住这个流程,理解了Android在控制Activity生命周期时是如何操作,以及是通过哪几个关键的类进行操作的就可以了,

    总结一下 Activity的启动流程:

    ​ 用户在Launcher程序里点击应用图标时,会通知AMS启动应用的入口Activity,AMS发现这个应用还未启动,则会通知Zygote进程孵化出应用进程,然后在这个dalvik应用进程里执行ActivityThread的main方法。应用进程接下来通知AMS应用进程已启动,AMS保存应用进程的一个代理对象,这样AMS可以通过这个代理对象控制应用进程,然后AMS通知应用进程创建入口Activity的实例,并执行它的生命周期方法

    现在也可以理解:

    ​ 如果应用的组件(包括所有组件Activity,Service,ContentProvider,Receiver) 被启动,肯定会先启动以应用包名为进程名的进程,这些组件都会运行在应用包名为进程名的进程里,并且是在主线程里。应用进程启动时会先创建Application对象,并执行Application对象的生命周期方法,然后才启动应用的组件。

    ​ 有一种情况比较特殊,那就是为组件设置了特殊的进程名,也就是说通过android:process设置进程名的情况,此时组件运行在单独的进程内。

    • 记录集
      不要使用 startActivityForResult(intent,RESULT_OK) 特此记录
    public void startActivity(Intent intent, @Nullable Bundle options) {
            if (options != null) {
                startActivityForResult(intent, -1, options);
            } else {
                // Note we want to go through this call for compatibility with
                // applications that may have overridden the method.
                startActivityForResult(intent, -1);
            }
        }
    //但是RESULT_OK  = -1;
    public static final int RESULT_OK  = -1;
    //得出结论 如果用RESULT_OK  作为请求码 你不可能从onActivityResult()里面收到任何回调.
    startActivityForResult(intent,RESULT_OK) = startActivity()
    

    本文链接地址

    相关文章

      网友评论

        本文标题:关于Activity你必须掌握的知识(本篇基于8.0去分析)

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