代碼位於: com.android.systemui.recent
工具: eclipse
主要問題:
1. 啟動方式
2. 怎么顯示最近任務?布局結構,數據來源。
3. 如何刪除?刪除后執行哪些動作?
1. 啟動方式
很自然地找到 com.andorid.systemui.recent.RecentsActivity ,然后 ctrl+alt+g 搜索引用,除去recent 中出現的,主要有兩處:1. Manifest.xml ; 2. BaseStatusBar
1) Manifest.xml中肯定是有的,Activity 需要注冊,那么看一下它的:
Manifest.xml
android:label="@string/accessibility_desc_recent_apps"
android:theme="@style/RecentsStyle"
android:excludeFromRecents="true"
android:launchMode="singleInstance"
android:exported="true">
如果通過intent 隱式啟動的話,action 為 com.android.systemui.TOGGLE_RECENTS,所以搜索這個字符串--沒有記過,那么就是顯式啟動,於是搜 com.andorid.systemui.recent.RecentsActivity或者RecentsActivity,找到了toggleRecentsActivity, 於是直接看toggleRecentsActivity。2) BaseStatusBar 中的主要是一個 一個方法:
toggleRecentsActivity, 有如下代碼:
BaseStatusBar
toggleRecentsActivity
Intent intent = new Intent(RecentsActivity.TOGGLE_RECENTS_INTENT);
intent.setClassName("com.android.systemui",
"com.android.systemui.recent.RecentsActivity");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
if (firstTask == null) {
if (RecentsActivity.forceOpaqueBackground(mContext)) {
ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_launch_from_launcher_enter,
R.anim.recents_launch_from_launcher_exit);
mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
UserHandle.USER_CURRENT));
} else {
// The correct window animation will be applied via the activity's style
mContext.startActivityAsUser(intent, new UserHandle(
UserHandle.USER_CURRENT));
}
}可以確認是通過 toggleRecentsActivity 方法啟動的了,於是接下來找toggleRecentsActivity 方法怎么被調用。
BaseStatusBar.toggleRecentsActivity
protected class H extends Handler {
public void handleMessage(Message m) {
Intent intent;
switch (m.what) {
case MSG_TOGGLE_RECENTS_PANEL:
if (DEBUG) Slog.d(TAG, "toggle recents panel");
if(!mSuperPowerSave){
toggleRecentsActivity();
}
break;在一個Handler 中,接受到一個what 為 MSG_TOGGLE_RECENTS_PANEL 的消息后,就會啟動 RecentActivity ,再看:
(A)這個消息什么時候被發送;
(B)該Handler 對象在哪里。
(A)這個消息什么時候被發送
在BaseStatusBar 中找到:
BaseStatusBar .toggleRecentApps
@Override
public void toggleRecentApps() {
int msg = MSG_TOGGLE_RECENTS_PANEL;
mHandler.removeMessages(msg);
mHandler.sendEmptyMessage(msg);
}
// ......繼續找
toggleRecentApps() ,結果如圖1:
圖1
可以看到有四個地方調用了,其中TableStatusBar 就不管了,看看其它三個調用分別是什么時機。
A1.handleMessage
com.android.systemui.statusbar.CommandQueue
private final class H extends Handler {
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
switch (what) {
//......
case MSG_TOGGLE_RECENT_APPS:
mCallbacks.toggleRecentApps();
break;
//......MSG_TOGGLE_RECENT_APPS消息又是怎么過來的了:
com.android.systemui.statusbar.CommandQueue
public void toggleRecentApps() {
synchronized (mList) {
mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS);
mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null).sendToTarget();
}
}看toggleRecentApps 的調用地方:
圖2
可以看出是系統的一些服務和Manager 會在相應的時機調用這個toggleRecentApps()方法。
所以這條線是這樣的:
系統在相應的時機(長按Home鍵......)調用 CommandQueue的toggleRecentApps();
CommandQueue的 toggleRecentApps(): 刪除消息隊列中的 what 為 MSG_TOGGLE_RECENT_APPS的所有消息,然后再發送一條what 為MSG_TOGGLE_RECENT_APPS 的消息;
CommandQueue的Handler 接收消息,調用handleMessage處理消息,對MSG_TOGGLE_RECENT_APPS的消息的處理方式是: mCallbacks.toggleRecentApps() ,即BaseStatusBar 的toggleRecentApps 方法;
BaseStatusBar的toggleRecentApps:發送MSG_TOGGLE_RECENTS_PANEL的消息;
BaseStatusBar 的 mHandler 接收到消息,調用handlerMessage 處理:這里又調用了 toggleRecentsActivity() 方法;
toggleRecentsActivity() :啟動了RecentsActivity.
A2.onClick
onClick 所在之處的代碼是一個onClickListener 對象:
private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
public void onClick(View v) {
toggleRecentApps();
}
};
//......
設置給導航欄的Recent按鈕:
mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
A3.onReceive
這個是PhoneStatusBar中注冊的一個BroadCastReceive中onReceive 方法。
小結:
啟動方式有三:1)系統啟動,如長按Home鍵,系統的某些服務啟動。2)導航欄按鈕;3)廣播