Android 7.0分屏原理及生命周期
来源:互联网 发布:mac装微软雅黑字体 编辑:程序博客网 时间:2024/06/10 01:28
Android 7.0分屏原理及生命周期
7.0分屏原理
- 7.0的Activity新增了onMultiWindowModeChanged方法,当页面在分屏或不分屏状态变换时,会回调这个方法。
分屏的任务管理器和虚拟按键在com/android/systemui目录下。长按多任务键时会调用PhoneStatusBar的toggleSplitScreenMode()方法。需要说明的是,多任务界面实际上是一个名叫RecentsActivity的Activity。
protected void toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) { if (mRecents == null) { return; } int dockSide = WindowManagerProxy.getInstance().getDockSide(); if (dockSide == WindowManager.DOCKED_INVALID) {//进入分屏模式,调出最近任务页面。 mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE, ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null, metricsDockAction); } else { EventBus.getDefault().send(new UndockingTaskEvent()); if (metricsUndockAction != -1) { MetricsLogger.action(mContext, metricsUndockAction); }}
需要分屏时会调用Recents的dockTopTask方法,该方法内部会调用RecentsImpl的dockTopTask,该方法除了在多任务界面做出任务管理“样式”的调整以外,还会调用SystemServicesProxy.moveTaskToDockedStack,在分屏模式下打开最近任务
public void dockTopTask(int topTaskId, int dragMode, int stackCreateMode, Rect initialBounds) { SystemServicesProxy ssp = Recents.getSystemServices(); // Make sure we inform DividerView before we actually start the activity so we can change // the resize mode already. if (ssp.moveTaskToDockedStack(topTaskId, stackCreateMode, initialBounds)) {//远程调用ActivityManagerService.moveTaskToDockedStack方法 EventBus.getDefault().send(new DockedTopTaskEvent(dragMode, initialBounds)); showRecents( false /* triggeredFromAltTab */, dragMode == NavigationBarGestureHelper.DRAG_MODE_RECENTS, false /* animate */, true /* launchedWhileDockingTask*/, false /* fromHome */, DividerView.INVALID_RECENTS_GROW_TARGET);}}
而该进程下的RecentsActivity则负责远程与PackageManager通信,拿到应用截图,添加到界面上
private void reloadStackView() { //省略部分代码 RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options(); loadOpts.runningTaskId = launchState.launchedToTaskId; loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks; loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails; loader.loadTasks(this, loadPlan, loadOpts); TaskStack stack = loadPlan.getTaskStack(); mRecentsView.onReload(mIsVisible, stack.getTaskCount() == 0); mRecentsView.updateStack(stack, true /* setStackViewTasks */); // Update the nav bar scrim, but defer the animation until the enter-window event boolean animateNavBarScrim = !launchState.launchedViaDockGesture; mScrimViews.updateNavBarScrim(animateNavBarScrim, stack.getTaskCount() > 0, null); //省略部分代码
}
那么7.0的Activity新增的方法onMultiWindowModeChanged是在什么时候调用的呢?回到刚才的SystemServicesProxy.moveTaskToDockedStack,该方法会跨进程调用ActivityManagerService.moveTaskToDockedStack
public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate, Rect initialBounds, boolean moveHomeStackFront) { enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToDockedStack()"); synchronized (this) { long ident = Binder.clearCallingIdentity(); try { if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToDockedStack: moving task=" + taskId + " to createMode=" + createMode + " toTop=" + toTop); mWindowManager.setDockedStackCreateState(createMode, initialBounds); final boolean moved = mStackSupervisor.moveTaskToStackLocked( taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS, "moveTaskToDockedStack", animate, DEFER_RESUME); if (moved) { if (moveHomeStackFront) { mStackSupervisor.moveHomeStackToFront("moveTaskToDockedStack"); } mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); } return moved; } finally { Binder.restoreCallingIdentity(ident); }}
}
该方法会调用StackSupervisor.moveTaskToStackLocked,在StackSuperviso中做尺寸调整等工作以外,最终调用TaskRecord.updateOverrideConfiguration()。若需要分屏,则会调用scheduleReportMultiWindowModeChanged方法
Configuration updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {//省略部分代码 if (mFullscreen != oldFullscreen) { mService.mStackSupervisor.scheduleReportMultiWindowModeChanged(this); } return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null;}
scheduleReportMultiWindowModeChanged最终调用ActivityThreadhandleMultiWindowModeChanged,并通过appToken找到需要回调的Activity
private void handleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode) { final ActivityClientRecord r = mActivities.get(token); if (r != null) { r.activity.dispatchMultiWindowModeChanged(isInMultiWindowMode); }}
Activity的dispatchMultiWindowModeChanged会回调onMultiWindowModeChanged,便可进行业务处理
分屏时Activity的生命周期
- 分三种情况
当前显示自己的应用页面,长按多任务键时出现分屏
onMultiWindowModeChanged(true)->onPause-onStop->onDestroy->onCreate->onStart- >onResume->onPause
分屏时长按多任务键,全屏显示自己的应用时
onStop->onDestroy->onCreate->onStart->onResume>onPause>onMultiWindowModeChanged(false)->onResume
当前显示其他应用,按多任务键出现自己的应用时
onMultiWindowModeChanged(true)->nDestroy->onCreate->onStart->onResume
参考资料
示例 | Android Developers
- Android 7.0分屏原理及生命周期
- Android 7.0 分屏原理分析
- servlet原理及生命周期
- Servlet的生命周期分及四个阶段?
- Servlet 生命周期及工作原理
- Servlet 生命周期及工作原理
- Servlet 生命周期及工作原理
- Android Activity及生命周期
- Android 分渠道打包原理
- Android framework学习笔记 -- 原生分屏原理
- Servlet的生命周期及工作原理
- session原理及生命周期和一些api
- Servlet的生命周期及工作原理
- Servlet 原理及生命周期(第一天)
- Servlet的生命周期及工作原理
- servlet的生命周期及工作原理
- Android 7.0分屏技术
- Android Service生命周期及用法!
- USB、UART、SPI、I2C、Ethernet、SD、SATA、PCI、 XGMII/XLGMII/CGMII总线的传输速度
- Java Mysql Emoji 配置
- 【OVS2.5.0源码分析】datapath之action分析(7)
- javac编译 编码GBK的不可映射字符
- activiti笔记
- Android 7.0分屏原理及生命周期
- c++学习笔记(2)字符串
- OJ算法
- linux 2.6下eeprom at24c08 i2c设备驱动(new style probe方式)
- margin属性
- ACDream1735-输油管道
- 博客旧址
- Android开发之入门基础篇-->拨号器的四种实现方式
- 求数字二进制表示中的1的个数