~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
最近Task模块
Recents extends SystemUI
start进行初始化
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BaseStatusBar中如下函数显示最近task
protected void toggleRecents() {
if (mRecents != null) {
mRecents.toggleRecents(mDisplay);
}
}
mRecents = getComponent(Recents.class);
Recents.java->toggleRecents(Display display)
mImpl.toggleRecents(growTarget);
RecentsImpl.java
public void toggleRecents(int growTarget) {
里面有4种情况
// Launch the next focused task
EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
// Notify recents to move onto the next task
EventBus.getDefault().post(new IterateRecentsEvent());
if (DEBUG) Log.d(TAG, "toggleRecents step3");
EventBus.getDefault().post(new ToggleRecentsEvent());
// Otherwise, start the recents activity
ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
startRecentsActivity(runningTask, isHomeStackVisible.value, true /* animate */,
growTarget);
最终调用RecentsImpl.java中的
private void startRecentsActivity(ActivityOptions opts) {
Intent intent = new Intent();
intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
| Intent.FLAG_ACTIVITY_TASK_ON_HOME);
if (opts != null) {
mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
} else {
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
}
EventBus.getDefault().send(new RecentsActivityStartingEvent());
}
启动RecentsActivity.java
public final static String RECENTS_PACKAGE = "com.android.systemui";
public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
recent 列表画面
recents.xml
recents_task_view_header.xml 是 app icon和title部分,对应TaskViewHeader.java
recents_task_view_header_overlay.xml
recents_empty.xml 没有recent app
RecentsView是recent的重要部分,显示最近app列表的,其中成员变量
private TaskStackView mTaskStackView;记录了全部的TaskViews,TaskView就是每个RecentApp
TaskView Override了onLongClick方法,作为拖动的入口
TaskView <---->Task
Task记录了对应的app intent等重要信息
onLongClick中有如下两句是处理事件的开始
EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
EventBus.getDefault().send(new DragStartEvent(mTask, this, mDownTouchPos));
*****************
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EventBus.Event
所有继承Event的类 extends EventBus.Event
src/com/android/systemui/recents/events/activity/* ------>画面迁移相关事件
src/com/android/systemui/recents/events/ui/dragndrop/* ------>拖拽相关事件
src/com/android/systemui/recents/events/ui/focus/* ------>focus变更相关事件
src/com/android/systemui/recents/events/ui/* ------>其他UI相关事件
onBusEvent
所有事件回调都是这个,只是事件类型不同
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
启动后Recent的隐藏
PhoneStatusBar中调用了disable
12-19 20:17:06.041 1624-1624/com.android.systemui D/PhoneStatusBar: disable: < EXPAND* icons alerts system_info BACK* HOME* RECENT* clock SEARCH* quick_settings >
RECENT*表示需要隐藏recent app画面
if ((state1 & StatusBarManager.DISABLE_RECENT) != 0) {
// close recents if it's visible
mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS);
}
接着调用BaseStatusBar中的
MSG_HIDE_RECENT_APPS
处理隐藏recents app的机能
case MSG_HIDE_RECENT_APPS:
hideRecents(m.arg1 > 0, m.arg2 > 0);
break;
调用Recents中的hideRecents
调用RecentsImpl中的hideRecents
EventBus.getDefault().post(new HideRecentsEvent(triggeredFromAltTab,
triggeredFromHomeKey));
通过EventBus发送了一个HideRecentsEvent
RecentsActivity的public final void onBusEvent(HideRecentsEvent event)
接收到EventBus的事件并进行处理
public final void onBusEvent(HideRecentsEvent event) {
if (event.triggeredFromAltTab) {
// If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
if (!mIgnoreAltTabRelease) {
dismissRecentsToFocusedTaskOrHome();
}
} else if (event.triggeredFromHomeKey) {
dismissRecentsToHome(true /* animateTaskViews */);
// Cancel any pending dozes
EventBus.getDefault().send(mUserInteractionEvent);
} else {
// Do nothing
}
}
以Home键为例
调用dismissRecentsToHome
其实是通过EventBus发送事件DismissRecentsToHomeAnimationStarted并带着一个LaunchHomeRunnable
LaunchHomeRunnable中进行动画和startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT);
这样就显示了Home Launcher
当然接收事件的有如下几个地方
RecentsView.java
public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
SystemBarScrimViews.java
public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
TaskStackView.java
public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
分别进行了不同的处理
归根结底都是要隐藏RecentsView
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
分屏处理--长按事件
DragStartEvent
接收此事件一共3处
RecentsView.java
public final void onBusEvent(DragStartEvent event) {
这里隐藏了clear all button,显示DockState
RecentsViewTouchHandler.java
public final void onBusEvent(DragStartEvent event) {
拖拽开始前的初始化处理,发送event DragStartInitializeDropTargetsEvent,寻找drop target
将dockstates添加到mVisibleDockStates中
// Add the dock state drop targets (these take priority)
TaskStack.DockState[] dockStates = getDockStatesForCurrentOrientation();
for (TaskStack.DockState dockState : dockStates) {
registerDropTargetForCurrentDrag(dockState);
dockState.update(mRv.getContext());
mVisibleDockStates.add(dockState);
}
getDockStatesForCurrentOrientation
可以获取到左右两个dock state
TaskStackView.java
public final void onBusEvent(DragStartEvent event) {
创建针对此事件的TaskView的动画,动画包括Z-order,alpha,size等的变化,并执行动画
TaskViewTransform.java动画封装类
DragStartInitializeDropTargetsEvent
只有一处处理此事件
TaskStackView.java
public final void onBusEvent(DragStartInitializeDropTargetsEvent event) {
if (ssp.hasFreeformWorkspaceSupport()) {
event.handler.registerDropTargetForCurrentDrag(mStackDropTarget);
event.handler.registerDropTargetForCurrentDrag(mFreeformWorkspaceDropTarget);
}
两个drop target
mStackDropTarget
mFreeformWorkspaceDropTarget
DockState
其实就是左右两边可以放置拖动item的target
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
分屏处理--拖动事件
RecentsViewTouchHandler.java
case MotionEvent.ACTION_MOVE:
if (mLastDropTarget != currentDropTarget) {
mLastDropTarget = currentDropTarget;
EventBus.getDefault().send(new DragDropTargetChangedEvent(mDragTask,
currentDropTarget));
}
DragDropTargetChangedEvent接收方有两个
RecentsView.java
public final void onBusEvent(DragDropTargetChangedEvent event) {
移动clear all btn的位置,DockState变更大小,从两边变成占据半屏
TaskStackView.java
public final void onBusEvent(DragDropTargetChangedEvent event) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
分屏处理--UP事件
RecentsViewTouchHandler的handleTouchEvent中
case MotionEvent.ACTION_UP:
EventBus.getDefault().send(new DragEndEvent(mDragTask, mTaskView,
!cancelled ? mLastDropTarget : null));
发送DragEndEvent
接收事件有5处
RecentsView.java
public final void onBusEvent(final DragEndEvent event) {
判断是否拖动到DockState上
如果是--->隐藏dockstate
不是 --->dockstate恢复默认状态
对clear btn改变显示隐藏状态
RecentsViewTouchHandler.java
public final void onBusEvent(DragEndEvent event) {
变量reset
mDragRequested = false;
mDragTask = null;
mTaskView = null;
mLastDropTarget = null;
SystemBarScrimViews.java
public final void onBusEvent(final DragEndEvent event) {
隐藏nav bar scrims
TaskStackView.java
public final void onBusEvent(final DragEndEvent event) {
移动taskview到最终位置
移动其他task到对应位置
TaskView.java
public final void onBusEvent(DragEndEvent event) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~