在1月9號晚體驗了小程序以后,我使用魅族手機清除當前已開啟的利用(多任務列表)的時候,我驚奇發現小程序竟然“獨立”于微信有自己的“生命周期”。
以下:
圖中的 查地鐵,摩拜單車 都是開啟的小程序。這樣的效果是否是和獨立的app1樣呢!我是覺得簡直1模1樣!
出于好奇,查閱相干資料(見文末參考文獻)
初步分析以下:
小程序和微信就是顯示在系統的任務列表也就是開啟的任務縮略圖那里,如上圖列出的就是最近啟動過的任務縮略圖。那末研究思路就有了:找出這個縮略圖的構成進程就可以找到答案了。其中有兩個重要的類以下:
// Recent apps
private RecentsPanelView mRecentsPanel;
private RecentTasksLoader mRecentTasksLoader;
// return a snapshot of the current list of recent apps
ArrayList<TaskDescription> getRecentTasks() {
cancelLoadingThumbnails();
ArrayList<TaskDescription> tasks = new ArrayList<TaskDescription>();
final PackageManager pm = mContext.getPackageManager();
final ActivityManager am = (ActivityManager)
mContext.getSystemService(Context.ACTIVITY_SERVICE);
final List<ActivityManager.RecentTaskInfo> recentTasks =
am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE);
ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)
.resolveActivityInfo(pm, 0);
HashSet<Integer> recentTasksToKeepInCache = new HashSet<Integer>();
int numTasks = recentTasks.size();
// skip the first task - assume it's either the home screen or the current activity.
final int first = 1;
recentTasksToKeepInCache.add(recentTasks.get(0).persistentId);
for (int i = first, index = 0; i < numTasks && (index < MAX_TASKS); ++i) {
final ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(i);
TaskDescription item = createTaskDescription(recentInfo.id,
recentInfo.persistentId, recentInfo.baseIntent,
recentInfo.origActivity, recentInfo.description, homeInfo);
if (item != null) {
tasks.add(item);
++index;
}
}
// when we're not using the TaskDescription cache, we load the thumbnails in the
// background
loadThumbnailsInBackground(new ArrayList<TaskDescription>(tasks));
return tasks;
}
縮略圖的核心獲得方法:
RecentsPanelView.java 中 調用
refreshRecentTasksList(recentTaskDescriptions);
而終究得調用getRecentTasks()方法
mRecentTaskDescriptions = mRecentTasksLoader.getRecentTasks();
通過源碼分析,不難得出Android系統中,顯示最近程序列表的View是 RecentsPanelView類,通過refreshRecentTasksList()方法加載程序列表,其中RecentTasksLoader 負責最后的加載.
分析到這里,已明白是怎樣回事了,小程序其實不是完全和微信獨立(只是看起來獨立了).”小程序”要實現和獨立app那樣有獨立的任務縮略圖(也就是入口), 只需要把目標activity設置為 新Task 方式啟動就能夠了。
點擊“開啟1個小程序吧”按鈕,就打開了新activity(小程序),去任務列表中查看,果然假想以下圖所示。
實現上面的效果,只是需要兩步:
1. AndroidManifest.xml中為 目標Activity 設置taskAffinity
<activity android:name=".MiniActivity"
android:label="小程序"
android:taskAffinity=".NewTask">
</activity>
2.以NEW_TASK方式啟動Activity
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,MiniActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
ps:原來開啟的小程序都在新的task里面而已
設置此狀態,首先會查找是不是存在和被啟動的Activity具有相同的taskAffinity的task(注意同1個利用程序中默許所有activity 的taskAffinity是1樣的)。如果有,就直接把這個棧整體移動到前臺,并保持棧中的狀態不變,即棧中的activity順序不變,如果沒有,則新建1個棧來寄存被啟動的activity.
也就是說,如果App已啟動,即便用FLAG_ACTIVITY_NEW_TASK新啟動1個Activity, 由于taskAffinity默許相同,也會被壓到1個task中, 自然recent panel 就看不到兩個入口了.
要實現預設的效果還需要為目標activity設置1個參數taskAffinity=“.NewTask”,簡單的說就是設置(新建)該activity自己的啟動方式。
目前有兩種方式:
1.在AndroidManifest.xml目標Activity添加 android:excludeFromRecents屬性:
android:excludeFromRecents="true"
2.在啟動Activity的時候設置FLAG: Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
參考文獻:
1.系統UI介紹
2.關于如何讓利用程序不顯示在“最近利用程序”的列表中
3.taskAffinity介紹