您的位置:首页 > 移动开发 > Android开发

Android onNewIntent()需要注意的一些问题

2017-06-16 17:20 337 查看
一、场景

  最近遇到一个需求:有A、B、C三个页面,A能跳到B,然后B会跳到C,C还能跳到B,反正B和C两个页面能互相跳,但是C页面点击返回的时候要回到A。(ps:页面之间有数据的传递)

  拿到需求我一下就想到的方案就是 把 B、C两个页面的启动模式设置成SignleTask:
android:launchMode="singleTask"
, 在B Intent跳转C时将B finish()掉,因为C在Activity栈里面永远也只有一个实例,这样当C点击返回时就会返回A了。~~细细一想没发现什么问题,很完美。

二、遇到问题

  然而事实总是残酷的,测试总是牛批的。当测试拿着数据来找我的时候我也懵了。经过调试我发现数据有点不对劲,因为B跳转C的时候会传递一个值(这里记为第一次给C传值),C里面会做一些操作然后更新数据传给B,B接收到数据然后更新第一次传递的值再传给C(这里记为第二次传值)。但是通过log发现第一次和第二次传递的值根本没有变化!

  经过查找我发现了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) {
}


翻译:
  当Activity启动方式设置成 singleTop,或者程序里面调用startActivity时使用FLAG_ACTIVITY_SINGLE_TOP标签时这个方法会被调用。无论哪种情况
只要当Activity在Activity栈的栈顶被重新启动而不是重新生成一个新的Activity实例时,onNewIntent()就会在之前那个已经启动过的Activity里面被调用。

 在接收到新意图之前,Activity将始终处于暂停状态,因此您可以依赖此方法后调用onResume。

  注意:getIntent() 始终返回的是之前的intent所传的数据,你可以使用setIntent(intent)去更新数据


  通过文档我们需要了解到的信息是:onNewIntent() 这个方法只有当进入一个已经打开过的Activity时才会调用,也就是第一次进入这个Activity时不会调用。而且如果两个acticity之间使用intent传值的话,第二次通过getIntent()获取的值将还是上一次的值!!!

  终于在这里发现了我所遇到的问题所在,开篇我说过我的C使用的SingleTask,而B在跳转前都会finish() 掉自己,所以C一直处于栈顶,所以当第二次跳转C时我的getIntent获取的还是旧的值,所以导致数据没变。

三、实验

下面通过实验来测试下,因为代码简单这里只提供主要的实验思路:

思路:定义两个Activity:A和B。启动模式都设置成SingleTask,A点击跳转B并传一个参数,然后finish A;B在点击跳转A也传递一个参数,用于判断修改第一次A传递给B的值。然后在B里面打印两次获取参数的值。

1、重写的几个主要的生命周期:

public class TestActivity extends BaseActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LogUtil.zLog().e("onCreate");
}
@Override
protected void onStart() {
super.onStart();
LogUtil.zLog().e("onStart");
}
@Override
protected void onRestart() {
super.onRestart();
LogUtil.zLog().e("onRestart");
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
LogUtil.zLog().e("onNewIntent");
}
@Override
protected void onResume() {
super.onResume();
LogUtil.zLog().e("onResume");
}
@Override
protected void onPause() {
super.onPause();
LogUtil.zLog().e("onPause");
}
@Override
protected void onStop() {
super.onStop();
LogUtil.zLog().e("onStop");
}
}


这里第一次我传递的是“1”,第二次传递的是“2”。

结果:(这里打印的只有TestActivity 的生命周期)

第一次进入 TestActivity
06-16 13:58:58.889 15959-15959/zz.mk.zgarden E/TAG:  - onCreate
06-16 13:58:58.889 15959-15959/zz.mk.zgarden E/TAG:  - onStart
06-16 13:58:58.909 15959-15959/zz.mk.zgarden E/TAG:  - onResume
//点击离开页面后
06-16 13:59:19.239 15959-15959/zz.mk.zgarden E/TAG:  - onPause
06-16 13:59:20.060 15959-15959/zz.mk.zgarden E/TAG:  - onStop

第二次进入TestActivity
06-16 13:59:31.171 15959-15959/zz.mk.zgarden E/TAG:  - onNewIntent
06-16 13:59:31.181 15959-15959/zz.mk.zgarden E/TAG:  - onRestart
06-16 13:59:31.181 15959-15959/zz.mk.zgarden E/TAG:  - onStart
06-16 13:59:31.191 15959-15959/zz.mk.zgarden E/TAG:  - onResume


根据结果我们能够看到第二次进入的时候onCreate方法压根都没走,onNewIntent正如文档所说第一次也没走。而我们一般获取参数都在onCreate里面获取,所以这样会导致参数不会变化。

既然知道了问题出在哪了,我们就知道怎么解决了。

这里我们只要在onCreate和onNewIntent里面都调用同一个获取参数的方法就好了:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState){
super.onCreate(savedInstanceState);
getExtraData();
}

@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
// intent.getStringExtra("TEST");
getExtraData();
}

private void getExtraData(){
test = getIntent().getStringExtra("TEST");
TextView.setText(test);
}


上面注意在onNewIntent方法里面要调用下
setIntent(intent);
不然数据还是不会变化,当然也可以直接使用
intent.getStringExtra("TEST");
获取的数据也是新的。不过充代码复用角度来看的话还是setIntent比较好点。

今天的分享就到这里了,有问题欢迎指出~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: