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

3 0
原创粉丝点击