如何清除启动Activity的Intent?

34

在开始时,Activity通过Intent启动并对该Intent执行某些操作。

当我更改Activity的方向时,它会重新加载,并将Intent传递给Activity。

我该如何清除该Intent以防止Activity再次使用它?

我尝试过setIntent(null),但没有效果。


Pixel应该拒绝明显错误的答案,接受@dcg的答案。这将为我节省大约一个小时的工作时间,因为我走了错误的道路。请参阅Dianne Hackborn在如何设置意图方面的帖子:https://groups.google.com/forum/#!msg/android-developers/vrLdM5mKeoY/ThkOonAbtloJ - JohnnyLambada
看看这个能否帮到你 - stackoverflow.com/a/19820057/313042 - Rajath
10个回答

30
我有类似的问题。这个对我很有帮助。 也许你还需要使用onSaveInstanceState(Bundle outState)并将额外的数据添加到Bundle中,以便inState不为null,但我不确定。
Intent activityIntent = null; // Subsequent times it's null

@Override 
protected void onCreate(Bundle inState) {
    super.onCreate(inState);
    .
    .
    if (inState!=null) {
        /*Recreating activity with a saved state*/
    } else {
        /*Creating activity*/
        activityIntent = getIntent(); // First time through intent is used
        /*Get your Extra Intent data here. You will be capturing data on 1st creation. */
}

我有一个类似的方法,可以让您保留原始意图中的选择性参数。 - dell116
5
当我从“最近使用的应用程序”列表中打开应用程序时,它对我无效,此前我是通过返回退出应用程序的。应用程序会以空的Bundle但先前的意图打开。 - CACuzcatlan

13

不要使用setIntent(null)。尽管有时可能有效,但在某些情况下,原始intent可能会返回。

相反,调用setIntent()使用一个简单的intent,它没有动作、数据或额外信息,例如new Intent(Context, Class)

实际上,一开始使用setIntent()并不是一个好的API设计决策。正如dcg所指出的那样,在你的savedInstanceState仍为空时,请确保只检查你的Intent第一次。


4
setIntent 只会让你更困惑 -- 不要使用它。请参考 @dcg 的答案。当一个 Activity 被销毁时,无论你怎么使用 setIntent,启动该 Activity 的原始 intent 总是会被重复使用。原始 Intent 完全保留在应用程序之外的 ActivityManager 中,setIntent 对其没有影响。请参考 Dianne Hackborn 的帖子:https://groups.google.com/forum/#!msg/android-developers/vrLdM5mKeoY/ThkOonAbtloJ - JohnnyLambada
谢谢你提供那篇文章的参考,@JohnnyLambada!我已经更新了答案以避免误导人们。 - Oleg Vaskevich
1
检查savedInstanceState == null是太棒了!!!这帮助我区分我是从启动器还是从打开电子邮件附件接收到的意图开始我的MainActivity。 +1 - Nathan Vance

3

Kotlin 中:

如果你想清除 intent,那么这是最好的选择。

intent.replaceExtras(Bundle())
intent.action = ""
intent.data = null
intent.flags = 0

2
或许可以详细说明为什么这是最佳选项。 - Jack H
根据我的看法,这是一个不错的选择,我也找不到其他选项。因为我想在运行时清除广播数据,所以我使用了这段代码,我的问题得到了解决。 - Safal Bhatia

3
如果你设置了意图动作,你可以通过 getIntent().setAction(""); 来清除它。
例如在 onCreate(...) 中:
...
String action = getIntent().getAction();
if (action != null) {
  if (action.equals(YOUR_ACTION_WHATEVER)) {
    doSomethingHere(); // do something here
    getIntent().setAction(""); // clear the action
  }
}
...

这将清除操作,否则每次旋转设备时都会调用它。

2
如果您使用setAction方法将Intent发送到您的活动,请在接收Intent时执行以下操作,以避免屏幕旋转时多次处理此Intent:
Intent i = getIntent();
i.setAction(null);
setIntent(i);

1

虽然这篇文章有些旧,但某些人可能仍会用得上。

不要浪费时间,如果您的应用被恢复,那么意图将再次出现。

在“Activity Resume”中使用起始意图,并添加一个额外的值即可。

putExtra("DONE", 0)

每次您的应用恢复时,请检查是否已经具有此值:
hasExtra("DONE")

易懂


1
它不起作用。我认为Android以不同的方式保存“Intent”,而不是在内存中。您只在运行时添加此值。当活动被杀死时,系统会再次检索原始“Intent”。 - Kimi Chiu

0
在我的情况下,我需要将数据设置为 null:
getIntent().setData(null);

0

intent.putExtra(YourKey,""); //将值重置为未知 setIntent(intent);


0

我的建议是使用一个布尔变量来切换,以检查您的活动是否已被创建。

否则,您可以查看您的onCreate方法,据我所知,这仅在首次创建活动时执行。


1
同意。使用 onRetainNonConfigurationInstance() 将旧活动的状态传递到新活动中。 - CommonsWare
3
实际上,每当屏幕方向发生变化时,onCreate() 方法也会被调用(此时应用程序基本上被销毁并重新创建)。 - source.rar

0
即使在手动清除意图和意图附加项之后,它们已被解析,似乎Activity.getIntent()仍将返回启动Activity的原始意图。
为了解决这个问题,我建议像这样做:
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // The Intent provided by getIntent() (and its extras) will persist through a restore
    // via savedInstance.  Because of this, restoring this activity from a
    // an instance that was originally started with extras (deep-link or 
    // pre-defined destination) may cause un-desired behavior
    // (ie...infinite loop of sending the user directly to somewhere else because of a
    // pre-defined alternate destination in the Intent's extras).
    //
    // To get around this, if restoring from savedInstanceState, we explicitly
    // set a new Intent *** to override the original Intent that started the activity.***
    // Note...it is still possible to re-use the original Intent values...simply
    // set them in the savedInstanceState Bundle in onSavedInstanceState.
    if (savedInstanceState != null) {
        // Place savedInstanceState Bundle as the Intent "extras"
        setIntent(new Intent().putExtras(savedInstanceState));
    }

    processIntent(getIntent())
}

private void processIntent(Intent intent) {
    if (getIntent().getExtras() == null) {
        // Protection condition
        return;
    }

    doSomething(intent.getExtras.getString("SOMETHING_I_REALLY_NEED_TO_PERSIST"));

    final String somethingIDontWantToPersist = 
        intent.getExtras.getString("SOMETHING_I_DONT_WANT_TO_PERSIST");

    if(somethingIDontWantToPersist != null) {
        doSomething(somethingIDontWantToPersist);
    }
}

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save selective extras from original Intent...
    savedInstanceState.putString("SOMETHING_I_REALLY_NEED_TO_PERSIST", "persistedValued");
    super.onSaveInstanceState(savedInstanceState);
}

这样,就有了一种机制可以在保留原始Intent的能力的同时,将原始Intent的某些部分明确地保留下来。

请注意,我没有测试所有的Activity启动模式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接