Start Activity process

Start Activity process

如何使用Intent做Activity的跳转

Intnet intent = new Intent(MainActivity.this,TestActivity.class);
startActivity(intent);

流程

  • . startActivity的函数,这个函数被声明在了Context类中,然后我们的Activity类有重写版本,所以会执行Activity类下的版本

    startActivity–》startActivityForResult --》mInstrumentation.execStartActivit

    上面有三个函数,基本上都是简单的判断和一些代码的封装,在最后一个函数中,执行了mInstrumentation对象下的execStartActivity函数,这个函数会做一些脱离应用进程的操作,准备通过IBinder机制将请求发送到Ams中。
    这个实现就是执行intent脱离我们的应用线程,然后发送IBinder消息(俗称IPC)到Ams中,到此处便结束了应用之旅,开始进入系统内部.

  • Ams(ActivityManagerService),因为是对外调用的接口,所以为了不做过多的逻辑处理,紧接着转发给了startActivityAsUser函数校验一下发起者身份。我们可以看到其余的参数都是透传过来的,但是最后多出来了一个UserId
    UserId:手机上的用户标示,类似于电脑多用户,通过 应用uid / 100000 计算得出,0为手机持有者,默认值为0
    Uid:应用id,普通用户从 10000 Pid:进程id

    AMS startActivity(0) --》startActivityAsUser–》ActivityStarter startActivityMayWait --》startActivityLocked --》startActivity(1)–》startActivity(2)–》startActivityUnchecked --> resumeFocusedStackTopActivityLocked --》ActivityStack resumeTopActivityUncheckedLocked --> resumeTopActivityInnerLocked --> ActivityThread scheduleLaunchActivity -->handleLaunchActivity --> performLaunchActivity --> mInstrumentation.callActivityOnCreate --> activity.performCreate --》onCreate

    startActivityMayWait做了两件重要的事情,一个是获取ResolveInfo,一个是获取ActivityInfo,就是目标Activity的基本信息。
    startActivityLocked仅仅是记录时间,然后清空mLastStartActivityRecord数组的位置,为即将要启动的Activity腾位置
    startActivity(1)函数就分析完了,写的很长,但是逻辑并不复杂,主要就是处理startActivityForResult的逻辑和校验权限,最后还创建了一个目标activity的ActivityRecord对象就完了。
    startActivity(2)函数很简单,也只是通知Wms(WindowManagerService)阻塞一下Surface,然后就转发到了startActivityUnchecked函数中继续处理了。
    startActivityUnchecked做的核心功能就是识别并且处理启动模式,以及关联的启动栈、任务栈,最后选择完合适的任务栈后就准备调用resumeFocusedStackTopActivityLocked继续开启Activity
    resumeFocusedStackTopActivityLocked函数定义在ActivityStackSupervisor类中,从类名上可以看得出来这个是个管理者,不参与具体实现,所以函数也很短,只是做简单的校验就立马转发。紧接着就被转发到了ActivityStack下的resumeTopActivityUncheckedLocked中了
    resumeTopActivityInnerLocked函数就是对目标页的很多状态判断,还有pause我们的启动者,然后通知AT(ActivityThread)准备启动.
    scheduleLaunchActivity函数内创建了一个ActivityClientRecord对象,然后通过handler发送命令LAUNCH_ACTIVITY,

Activity 显示(WMS)

接上Activity onCreate -->Window setContentView -->generateLayout–>inflate

  • PhoneWindow.setContentView()里先执行了installDecor(),这个方法也是第一时间执行generateDecor(),其实就是new出来一个DecorView。DecorView是一个根布局,是一个FrameLayout。DecorView如果初始化完成,会是这样的结构。当然这只是其中的一种,事实上会根据主题,Title情况而有不同的结构。
    在这里插入图片描述

  • generateLayout方法里,layoutResource会根据是否dialog情况,title情况,actionbar情况,去取不同的xml资源。inflate出来后DecorView会调用addView方法把它添加进自身里。

1.Activity里面setContentView,实际上是利用PhoneWindow类创建DecorView,然后inflater出xml布局,放进DecorView内。此时View层级结构已经准备好,但还没跑measure、layout和draw三件套,也没有被大佬WMS接管显示出来。

2.想被WMS接管,需要操作IPC那套流程,所以需要使用WindowManager进行操作,它会通过ViewRootImpl,使用IWindowSession和IWindow两个IPC接口(应用程序访问WMS使用IWindowSession,WMS访问应用程序使用IWindow),最终让WMS接管。

3.界面显示出来是,会经过一系列流程条用到ViewRootImpl.performTraversals方法,里面会从DecorView开始,递归的执行measure、layout和draw三件套方法,最终确定大小,绘制界面。

多用户多屏显示异常问题

  • 问题: 多用户并显示多屏时,显示异常,某些activity只显示在default display上面。

    • 情况一:在第二屏第二用户上长按某APP,选择app info,settings的activity会在display 0上显示出来。
    • 情况二:APP里面调用其他activity,也会在默认显示屏上显示出来。
  • 分析:原生android已经支持多用户显示多屏上,但支持还不够完善,比如这里的activity,以及相应的dialog,toast,均会显示在display 0上。

  • 代码分析(情况一):

  • showAppDetailsAsUser --》startActivityAsUser–》executeRequest

  • startActivityAsUser中的/* resultTo= */ null,导致后续的executeRequest中的sourceRecord没有初始化,后续的startActivityUnchecked中的display被设置成了default display,也就是display 0

  • 问题解决:

  • 获取调用app的display的info,来设置当前启动activity的display info

在executeRequest中插入
+        int calling_displayID = INVALID_DISPLAY;
+        ActivityRecord callerRecord = null;
+        if(callerApp != null) {
+            callerRecord = callerApp.getConfigActivityRecord();
+            if(callerRecord != null) {
+                calling_displayID = callerRecord.getDisplayId();
+            }
+        }
+        if (calling_displayID != INVALID_DISPLAY && checkedOptions != null){
+           //call from APP property
+            if (calling_displayID != checkedOptions.getCallerDisplayId()) {
+                checkedOptions.setCallerDisplayId(calling_displayID);
+            }
+        } else if (sourceRecord == null) {
+           //call from APP internal
+            sourceRecord = callerRecord;
+        }
+
         mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                 request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值