我们知道,我们可以通过startActivity(Intent intent)方法来启动一个新的activity,其中intent负责交互数据的传递。当新启动的activity已经存在并且可复用的时候,情况就会发生一些微妙变化。原来启动传入的intent数据会不会消失?新传入的intent会不会立即生效?在Activity中有个onNewIntent()方法,通过分析它,可以理解在复用activity的数据传递问题。
onNewIntent方法一般用于lanchmode为singleTop,singleTask,singleInstance等可复用的activity中,当这些已实例化的activity重新被复用时,就会调用onNewIntent方法。正如字面上的意思,onNewIntent负责处理activity收到的新intent。
Activity中onNewIntent源码如下:
/**
* This is called for activities that set launchMode to "singleTop" in
* their package, or if a client used the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP}
* flag when calling {@link #startActivity}. In either case, when the
* activity is re-launched while at the top of the activity stack instead
* of a new instance of the activity being started, onNewIntent() will be
* called on the existing instance with the Intent that was used to
* re-launch it.
*
* <p>An activity will always be paused before receiving a new intent, so
* you can count on {@link #onResume} being called after this method.
*
* <p>Note that {@link #getIntent} still returns the original Intent. You
* can use {@link #setIntent} to update it to this new Intent.
*
* @param intent The new intent that was started for the activity.
*
* @see #getIntent
* @see #setIntent
* @see #onResume
*/
protected void onNewIntent(Intent intent) {
}
首先我们来看这句话:
when the activity is re-launched while at the top of the activity stack instead of a new instance of the activity being started, onNewIntent(Intent intent) will be called on the existing instance with the Intent that was used to re-launch it.
意思是当activity没有建立新实例,而是被重新复用并且处于任务栈的栈顶时,该activity的onNewIntent(Intent intent)方法会执行,其中的intent参数为复用activity的intent。
An activity will always be paused before receiving a new intent, so you can count on being called after this method.
onNewIntent()方法会在onResume()方法之前执行,这样我们可以在onNewIntent方法对新传来的intent进行一些处理。
Note that {@link #getIntent} still returns the original Intent. You can use {@link #setIntent} to update it to this new Intent.
值得注意的是,当我们复用activity时,getIntent()方法依旧返回的是原来的intent。可以看到,传入的新intent并没有立即生效,只是放在onNewIntent方法的参数中,原来的intent数据也没有消失,我们可以根据需求随意调用旧intent的或新intent,如果需要在复用activity过程中获取新intent中的数据,需要采用如下方式:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent != null)
setIntent(intent);
}
再在onResume()方法里调用getIntent(),即可得到新的数据。
另外,onNewIntent()代码说明里提到:
/**
* This is called for activities that set launchMode to "singleTop" in
* their package, or if a client used the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP}
* flag when calling {@link #startActivity}.
* /
这句话的意思是,onNewIntent()这个方法能被launchmode为singleTop 或 Intent Flag为FLAG_ACTIVITY_SINGLE_TOP的activity复用时调用。但是,launchmode 为singleTask,singleIntance 的activity也可以被复用,也会调用onNewIntent()方法,说明里为什么没有提及呢?个人觉得是singleTask,singleIntance 内部实现中也设置了FLAG_ACTIVITY_SINGLE_TOP flag ,有兴趣的朋友可以帮我解答~另外,让很多人困惑的是,当我们使用FLAG_ACTIVITY_SINGLE_TASK 时,为避免出现activity多实例,必须加上FLAG_ACTIVITY_SINGLE_TOP 标签,有的人说这是一个BUG,不知道它们看了onNewIntent()的说明后,还会这么认为吗?我把它理解成FLAG_ACTIVITY_SINGLE_TOP flag就是为了调用onNewIntent()存在的。不过可以肯定的是,google的android doc还有待完善平衡……