一、API描述如下
大概意思是当Activity被设以singleTop模式启动,当需要再次响应此Activity启动需求时,会复用栈顶的已有Activity,还会调用onNewIntent方法。并且,再接受新发送来的intent(onNewIntent方法)之前,一定会先执行onPause方法。
二、onNewIntent与启动模式
前提:ActivityA已经启动过,处于当前应用的Activity任务栈中;
当ActivityA的LaunchMode为Standard时:
由于每次启动ActivityA都是启动新的实例,和原来启动的没关系,所以不会调用原来ActivityA的onNewIntent方法
当ActivityA的LaunchMode为SingleTop时:
如果ActivityA在栈顶,且现在要再启动ActivityA,这时会调用onNewIntent()方法 ,生命周期顺序为:
onCreate--->onStart--->onResume---onPause--->onNewIntent--->onResume
当ActivityA的LaunchMode为SingleInstance,SingleTask:
如果ActivityA已经在任务栈中,再次启动ActivityA,那么此时会调用onNewIntent()方法,生命周期调用顺序为:
onPause--->跳转其它页面--->onCreate--->onStart--->onResume---onPause--->跳转A--->onNewIntent--->onRestart--->onStart--->onResume
因此:onNewIntent在情况1下调用,在情况2不调用
更准确的说法是,只对SingleTop(且位于栈顶),SingleTask和SingleInstance(且已经在任务栈中存在实例)的情况下,再次启动它们时才会调用,即只对startActivity有效,对仅仅从后台切换到前台而不再次启动的情形,不会触发onNewIntent
三、注意事项
通过前面我们知道,如果一个Activity已经启动过,并且存在当前应用的Activity任务栈中,启动模式为singleTask,singleInstance或singleTop(此时已在任务栈顶端),那么在此启动或回到这个Activity的时候,不会创建新的实例,也就是不会执行onCreate方法,而是执行onNewIntent方法,如下所示:
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);//must store the new intent unless getIntent() will return the old one
}
我们需要知道,在内存吃紧的情况下,系统可能会kill掉后台运行的 Activity ,如果不巧要启动的那个activity实例被系统kill了,那么系统就会调用 onCreate 方法,而不调用 onNewIntent 方法。这里有个解决方法就是在 onCreate 和 onNewIntent 方法中调用同一个处理数据的方法,如下所示:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getNewIntent();
}
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);//must store the new intent unless getIntent() will return the old one
getNewIntent();
}
private void getNewIntent(){
Intent intent = getIntent(); //use the data received here
}
注意onNewIntent()中的陷阱:
有时候,我们在多次启动同一个栈唯一模式下的activity时,在onNewIntent()里面的getIntent()得到的intent感觉都是第一次的那个数据。对,这里就是这个陷阱。因为它就是会返回第一个intent的数据。就是这么坑。
原因就是我们没有在onNewIntent()里面设置setIntent(),将最新的intent设置给这个activity实例。
在这里,如果你没有调用setIntent()方法的话,则getIntent()获取的intent都只会是最初那个intent(Note that getIntent() still returns the original Intent. You can use setIntent(Intent) to update it to this new Intent.)。