在上一篇文章中已经讲解了第一步,从PhoneStatusBar.java到Recents.java的流程,如果有需要可以点击上一篇。
在Recents.java中讲解了当我们调用dockTopTask(…)函数时会判断条件,如果可以进入分屏且是systemuser时,就跳转到RecentsImpl.dockTopTask(…)函数中。
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)) {
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);
}
}
代码位置:framework/base/packages/SystemUI/…/RecentsImpl.java
介绍下参数:
- topTaskId:就是获取的进入分屏应用的taskID,这个id是唯一的,可以用来区别app
- dragMode :NavigationBarGestureHelper.DRAG_MODE_NONE
- stackCreateMode : ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
- initialBounds: 全屏大小,例如当前机器分辨率是1920*1200,那么这个值就是(0, 0, 1920,1200)
SystemServicesProxy ssp = Recents.getSystemServices();
ssp.moveTaskToDockedStack(topTaskId, stackCreateMode, initialBounds)
这里是通过分屏应用的taskid,把应用由当前的stack移动到dockstack中,这部分内容在后续介绍分屏的services中会详细介绍,这里只做简单说明。
流程图:
介绍一下AndroidN上SystemUI在不同类之间传递消息的方式之一:
EventBus.getDefault().send(new xxxEvent(...));
public final void onBusEvent(xxxEvent event) {}
这两个一定是成对出现,xxxEvent必须一致,这样就可以在不同的类之间传递消息,这样就简化很多,而且可以做到发送一次,多各类都能接收到消息,不需要像之前一样写接口。
但是想使用这种方式在类中也是需要注册的,只有按照下图的方式注册过,才能接收到消息,否则是无效的。
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
EventBus.getDefault().register(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
EventBus.getDefault().unregister(this);
}
我们也可以扩展消息,可以在framework/base/packages/SystemUI/src/com/android/systemui/recents/events/activity/下添加对应的类
当移动task完成后,发送消息EventBus.getDefault().send(new DockedTopTaskEvent(dragMode, initialBounds));
在DividerView.java中有public final void onBusEvent(DockedTopTaskEvent event) {…}接收到消息,更新状态,主要是把mDockedRect改为全屏大小,这里显示的区域是进入分屏应用的区域。
接下来启动RecentActivity,在RecentsActivity中的onStart()方法中:
- EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));通知PhoneStatusBar,RecentsActivity显示了,改变状态
- mRecentsView.getViewTreeObserver().addOnPreDrawListener(mRecentsDrawnEventListener);这里是重点,mRecentsDrawnEventListener在注册监听后,就会发送消息EventBus.getDefault().post(new RecentsDrawnEvent());告诉DividerView去修改进入分屏应用的bounds
DividerView接收到消息:public final void onBusEvent(RecentsDrawnEvent drawnEvent) {…}
- mState.animateAfterRecentsDrawn:true
- mState.growAfterRecentsDrawn:false