365

Is it possible to start an activity on the stack, clearing the entire history before it?

The situation

I have an activity stack that either goes A->B->C or B->C (screen A selects the users token, but many users only have a single token).

In screen C the user may take an action which makes screen B invalid, so the application wants to take them to screen A, regardless of whether it is already in the stack. Screen A should then be the only item on the stack in my application.

Notes

There are many other similar questions, but I haven't found anything that answers this exact question. I tried calling getParent().finish() - this always results in a null pointer exception. FLAG_ACTIVITY_CLEAR_TOP only works if the activity is already on the stack.

4

13 に答える 13

714

APIレベル11では、このためだけに新しいインテントフラグが追加されました:Intent.FLAG_ACTIVITY_CLEAR_TASK

明確にするために、これを使用してください:

Java

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

Kotlin

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK

残念ながら、APIレベル<= 10の場合、これに対するクリーンな解決策はまだ見つかりません。「DontHackAndroidLikeThis」ソリューションは確かに純粋なハッカーです。あなたはそれをすべきではありません。:)

編集: @ Ben Pearsonのコメントによると、API <= 10の場合、同じものにIntentCompatクラスを使用できるようになりました。IntentCompat.FLAG_ACTIVITY_CLEAR_TASKフラグを使用してタスクをクリアできます。したがって、APIレベル11より前のバージョンもサポートできます。

于 2011-03-17T20:10:09.090 に答える
54

ケース1:2つのアクティビティAとBのみ:

ここで、アクティビティフローはA-> Bです。Bから戻るボタンをクリックすると、アプリケーションを閉じる必要があります。次に、AからアクティビティBを開始するときに、finish()を呼び出すだけで、AndroidがアクティビティAをBackstackに保存できなくなります。アプリケーションのロード/スプラッシュ画面。

Intent newIntent = new Intent(A.this, B.class);
startActivity(newIntent);
finish();

ケース2:2つ以上のアクティビティ:

A-> B-> C-> D-> Bのようなフローがあり、アクティビティDからのアクティビティBで戻るボタンをクリックした場合は、を使用する必要があります。

Intent newIntent = new Intent(D.this,B.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);

ここで、アクティビティBは、Intent.FLAG_ACTIVITY_CLEAR_TOPとIntent.FLAG_ACTIVITY_NEW_TASKがスタックをクリアして最上位のインスタンスにするため、新しいインスタンスではなくバックスタックから開始されます。したがって、戻るボタンを押すと、アプリケーション全体が終了します。

于 2013-05-03T12:45:55.383 に答える
51

Androidの新しいバージョン>=API16を使用する場合finishAffinity()

このアプローチは、API16以上に適しています。

Intent mIntent = new Intent(mContext,MainActivity.class);
finishAffinity();
startActivity(mIntent);
  • これは、新しいアクティビティを開始するのと同じで、すべてのスタックをクリアします。
  • またはMainActivity/FirstActivityに再起動します。
于 2016-09-14T07:19:11.090 に答える
26

私もこれに数時間を費やしました...そしてFLAG_ACTIVITY_CLEAR_TOPがあなたが望むもののように聞こえることに同意します:起動されているアクティビティを除いてスタック全体をクリアし、[戻る]ボタンでアプリケーションを終了します。ただし、Mike Repassが述べたように、FLAG_ACTIVITY_CLEAR_TOPは、起動するアクティビティがすでにスタックにある場合にのみ機能します。アクティビティがない場合、フラグは何もしません。

何をすべきか?起動中のアクティビティをFLAG_ACTIVITY_NEW_TASKを使用してスタックに配置します。これにより、そのアクティビティが履歴スタック上の新しいタスクの開始になります。次に、FLAG_ACTIVITY_CLEAR_TOPフラグを追加します。

これで、FLAG_ACTIVITY_CLEAR_TOPがスタック内の新しいアクティビティを見つけに行くと、そこにあり、他のすべてがクリアされる前にプルアップされます。

これが私のログアウト機能です。Viewパラメータは、関数がアタッチされているボタンです。

public void onLogoutClick(final View view) {
    Intent i = new Intent(this, Splash.class);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    startActivity(i);
    finish();
}
于 2013-10-18T15:29:06.207 に答える
13

スタックを変更しないでください。Androidの戻るボタンはWebブラウザと同じように機能するはずです。

私はそれを行う方法を考えることができますが、それはかなりのハックです。

  • singleTaskに追加して、アクティビティを作成します。AndroidManifest

    <activity android:name=".activities.A"
              android:label="@string/A_title"
              android:launchMode="singleTask"/>
    
    <activity android:name=".activities.B"
              android:label="@string/B_title"
              android:launchMode="singleTask"/>
    
  • Applicationどこに行くかのロジックを保持する拡張。

例:

public class DontHackAndroidLikeThis extends Application {

  private Stack<Activity> classes = new Stack<Activity>();

  public Activity getBackActivity() {
    return classes.pop();
  }

  public void addBackActivity(Activity activity) {
    classes.push(activity);
  }
}

AからBへ:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(A.class); 
startActivity(this, B.class);

BからCへ:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(B.class); 
startActivity(this, C.class);

Cの場合:

If ( shouldNotGoBackToB() ) {
  DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
  app.pop();
}

スタックから戻るボタンを処理しpop()ます。

繰り返しますが、これを行うべきではありません:)

于 2010-08-13T01:59:03.610 に答える
13

を使用して新しいアクティビティを開始した直後に、現在のアクティビティが新しいアクティビティの後ろにスタックされないように、startActivity必ず呼び出してください。finish()

于 2012-04-04T16:44:45.870 に答える
8

高度な再利用可能なKotlin:

setterメソッドを使用してフラグを直接設定できます。Kotlinでは、Javaのビット単位またはor代わり|になります。

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

これを定期的に使用する場合は、インテント拡張関数を作成してください

fun Intent.clearStack() {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

その後、インテントを開始する前に、この関数を直接呼び出すことができます

intent.clearStack()

他の状況でフラグを追加するオプションが必要な場合は、オプションのパラメーターを拡張関数に追加します。

fun Intent.clearStack(additionalFlags: Int = 0) {
    flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
于 2020-01-07T20:07:03.483 に答える
5

これを試して:

Intent logout_intent = new Intent(DashboardActivity.this, LoginActivity.class);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(logout_intent);
finish();
于 2017-06-13T04:29:01.257 に答える
5

以下のコードを試してください、

Intent intent = new Intent(ManageProfileActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
                Intent.FLAG_ACTIVITY_CLEAR_TASK| 
                Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
于 2018-11-14T08:39:59.777 に答える
3

私にとって、上記の方法はどれも機能しません。

これを行うだけで、以前のすべてのアクティビティがクリアされます。

finishAffinity() // if you are in fragment use activity.finishAffinity()
Intent intent = new Intent(this, DestActivity.class); // with all flags you want
startActivity(intent)
于 2019-05-24T10:38:28.560 に答える
2
Intent i = new Intent(MainPoliticalLogin.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
于 2017-12-13T11:56:04.517 に答える
-1

AndroidエミュレーターがEclipseDDMSツールへの接続に失敗し、adbを手動で開始するように要求する場合があります。その場合、コマンドプロンプトを使用してadbを開始または停止できます。

于 2016-10-06T09:08:54.207 に答える
-2

単純すぎるハックを見つけました。これを実行して、次のように新しい要素を追加します AndroidManifest。-

<activity android:name=".activityName"
          android:label="@string/app_name"
          android:noHistory="true"/>

android:noHistoryスタックから不要なアクティビティをクリアします。

于 2016-07-19T08:43:59.067 に答える