原文地址:Overview Screen
一、前言
主页(overview screen)也叫recent screen、recent task list、recent apps,是一个系统级UI,能够列举最近访问的activity和task。用户可以在这个UI中选择或者移除task。从Android 5.0(API 21)开始,Android支持同一个activity的不同实例在overview screen中显示为多个task。例如,Google Drive可以有一个task显示多个Google documents,而每个document也可以在overview screen中显示为一个task,如图1(个人理解:document是某个activity在overview screen的UI显示,它可以独占一个task单独显示,也可以有多个document显示在同一task中)。
通常,由系统定义你的task跟activity如何显示在overview screen上即可,你不需要改变这些行为。当然,你也可以自定义activity怎样和什么时候显示在overview screen上:使用ActivityManager.AppTask可以管理task,使用intent的flag可以指定什么时候activity加入overview screen或者从overview screen移除(在manifest文件中指定<activity>
的属性也可以)。
二、向overview screen添加task
通过intent添加flag可以很好的控制什么时候/怎样在overview screen打开或者重新打开document。通过<activity>
添加属性,你可以控制是在新的task打开document还是在已存在的task打开document。
2.1 使用intent的flag添加task
通过ActivityManager.AppTask的startActivity()方法,并传入一个intent(在此intent中通过addFlags()方法添加FLAG_ACTIVITY_NEW_DOCUMENT),可以让系统在overview screen中将你的activity视为一个新的task。
注意:FLAG_ACTIVITY_NEW_DOCUMENT替代了FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET,后者从Android 5.0(API 21)开始废弃
如果你在新建document时加入了FLAG_ACTIVITY_MULTIPLE_TASK,那么系统会新建一个task,并将目标activity作为根activity。此flag可以让同一个document在多个task中打开。下面是main activity的一些代码:
public void createNewDocument(View view) {
final Intent newDocumentIntent = newDocumentIntent();
if (useMultipleTasks) {
newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
}
startActivity(newDocumentIntent);
}
private Intent newDocumentIntent() {
boolean useMultipleTasks = mCheckbox.isChecked();
final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, incrementAndGet());
return newDocumentIntent;
}
private static int incrementAndGet() {
Log.d(TAG, "incrementAndGet(): " + mDocumentCounter);
return mDocumentCounter++;
}
}
注意:使用FLAG_ACTIVITY_NEW_DOCUMENT的前提是,目标activity在manifest中指定的launchMode为standard(android:launchMode=”standard”)
在上面的示例中,当main activity启动新activity时,系统会在已存在的task中寻找符合intent指定的组件名称(component name)和intent数据的activity。如果没有找到这样的task,或者intent中包含FLAG_ACTIVITY_MULTIPLE_TASK,那么系统会新建一个task并将目标activity作为此task根activity;如果找到了这样的task,那么系统会将此task放到前台,并将新的intent传递给目标activity的onNewIntent()方法。新的activity得到此intent后会在overview screen中新建一个document,代码如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_document);
mDocumentCount = getIntent()
.getIntExtra(DocumentCentricActivity.KEY_EXTRA_NEW_DOCUMENT_COUNTER, 0);
mDocumentCounterTextView = (TextView) findViewById(
R.id.hello_new_document_text_view);
setDocumentCounterText(R.string.hello_new_document_counter);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
/* If FLAG_ACTIVITY_MULTIPLE_TASK has not been used, this activity
is reused to create a new document.
*/
setDocumentCounterText(R.string.reusing_document_counter);
}
2.2 使用activity属性添加task
activity可以在manifest文件的<activity>
标签下添加属性:android:documentLaunchMode,以控制activity的document。这个属性有四个值:
- intoExisting
activity会重用存在的task放置document。相当于添加了FLAG_ACTIVITY_NEW_DOCUMENT,且没有添加FLAG_ACTIVITY_MULTIPLE_TASK - always
activity为document新建一个task,即使这个document已经打开了。相当于添加了FLAG_ACTIVITY_NEW_DOCUMENT和FLAG_ACTIVITY_MULTIPLE_TASK - none
activity不会为document新建task。overview screen会将此activity视为默认状态:为此应用显示单独的task,该任务将从用户上次调用的任意Activity开始继续执行 - never
activity不会为document新建task。这个值对应的逻辑重写了FLAG_ACTIVITY_NEW_DOCUMENT与FLAG_ACTIVITY_MULTIPLE_TASK,如果intent中有这两个flag(或之一),那么overview screen会为此应用显示单独的task,该任务将从用户上次调用的任意Activity开始继续执行
注意:“intoExisting”与“always”要求activity的launchMode必须为standard。如果documentLaunchMode未指定,会默认使用“none”
三、移除task
默认情况下,document对应的activity结束时,会自动从overview screen移除。你可以通过在ActivityManager.AppTask类添加intent的flag或使用<activity>
属性修改默认行为。
将<activity>
的android:excludeFromRecents属性设置为true,可以随时将task从overview screen完全移除。
设置<activity>
的android:maxRecents可以限制你的应用能在overview screen显示的task的最大数量。默认为16。当task数量达到最大数量时,最早使用的task将会从overview screen移除。android:maxRecents可以设置的最大值为50(小内存设备中是25);小于1的值无效。
3.1 使用AppTask移除task
在新建task的activity中,你可以通过finishAndRemoveTask()方法,移除task和task中所有的activity。
public void onRemoveFromRecents(View view) {
// The document is no longer needed; remove its task.
finishAndRemoveTask();
}
注意:finishAndRemoveTask()方法重写了FLAG_ACTIVITY_RETAIN_IN_RECENTS(此flag在后面会讲到)
3.2 保存已结束的task
如果你想要在activity被结束后仍然将task保持在overview screen,可以在启动此activity的intent中通过addFlags()添加FLAG_ACTIVITY_RETAIN_IN_RECENTS。
private Intent newDocumentIntent() {
final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, incrementAndGet());
return newDocumentIntent;
}
将<activity>
的android:autoRemoveFromRecents属性设置为false可以达到同样的效果(document activity的默认值为true,regular activity的默认值为false)。这个属性会重写FLAG_ACTIVITY_RETAIN_IN_RECENTS。