13

私が理解しているように、アクティビティが破棄されることは、アクティビティが終了することと同等ではありません。

  • 終了した
    • アクティビティがバック スタックから削除されます。
    • finish()これは、プログラムによって (たとえば、 を呼び出すことによって)、またはユーザーが戻るキーを押すことによって (暗黙的に を呼び出すことによって)トリガーできますfinish()
    • アクティビティを終了すると、アクティビティが破棄されます。
  • 破壊されました
    • Android OS は、目に見えないアクティビティを破棄してメモリを回復する場合があります。ユーザーがアクティビティに戻ると、アクティビティが再作成されます。
    • ユーザーが画面を回転すると、アクティビティは破棄され、再作成されます。
    • 参考:アクティビティの再作成

では、破棄されたアクティビティを終了するにはどうすればよいですか? finish()メソッドにはオブジェクトが必要ですActivityが、アクティビティが破棄された場合、オブジェクトがありませActivityん。破棄されたアクティビティへの参照を保持する必要はありませんか?


ケーススタディ:

私は activity を持っておりa、それは を開始bし、次にc( を使用してActivity.startActivity()) 開始するので、バックスタックは次のようになります。

a → b → c

ではc、ユーザーがフォームに入力し、[送信] ボタンをタップします。を使用して、リモート サーバーに対してネットワーク要求が行われますAsyncTask。タスクが完了したら、トーストを表示し、を呼び出してアクティビティを終了しc.finish()ます。完全。

次のシナリオを検討してください。

非同期タスクの進行中に、ユーザーは別のアプリに切り替えます。その後、Android OS は、メモリの制約により、3 つのアクティビティ ( ab、 ) をすべて破棄することを決定しました。cその後、非同期タスクが完了します。どうすれば終了しcますか?

私が試したこと:

  • 電話c.finish()
    • cは破壊されているため、できません。
  • 電話b.finishActivity()
    • bは破壊されているため、できません。
  • と一緒に使用Context.startActivity()して、上FLAG_ACTIVITY_CLEAR_TOPに上げbて仕上げcます。

    // appContext is an application context, not an activity context (which I don't have)
    Intent intent = new Intent(appContext, B.class);    // B is b's class.
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    appContext.startActivity(intent);
    
    • 失敗し、appContext.startActivity()例外をスローします:

android.util.AndroidRuntimeException: アクティビティ コンテキストの外部から startActivity() を呼び出すには、FLAG_ACTIVITY_NEW_TASK フラグが必要です。これは本当にあなたが望むものですか?

編集: 明確化:非同期タスクが終了するまで待機し、cサーバーの応答に基づいて終了するかどうかを決定する必要があります。

4

6 に答える 6

3

android.util.AndroidRuntimeException:アクティビティコンテキストの外部からstartActivity()を呼び出すには、FLAG_ACTIVITY_NEW_TASKフラグが必要です。これは本当にあなたが望むものですか?


  • この例外は、バックグラウンドスレッドまたはサービスからアクティビティを開始するときに発生していました。「ランチャー」 タイプの動作が必要な場合は常に、
    FLAG_ACTIVITY_NEW_TASKフラグを渡す必要があります。

    • mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);この例外を回避するために追加するだけです。

  • アクティビティを強制終了する方法はお勧めしません。Androidに処理させてください。すでに破壊されている活動を終了する意味はありません。

さて、あなたは何ができますか?

  • アプリがフォアグラウンドにないときにアクティビティを終了する際に問題が発生した場合は、セキュリティチェックを実装して、アプリがフォアグラウンドにあるときにのみアクティビティを終了してバックスタックアクティビティに進むか、その手順をスキップすることができます。

  • アプリがバックグラウンドにあるときにアクティビティを強制終了しようとしていると思います。これを行うのは少し難しいようですが、onUserLeaveHintfinish();を使用して、アプリがバックグラウンドで実行されるタイミングを決定し、アクティビティを終了するか、を追加してアクティビティを終了することができますonStop()onPost()例外を回避するために、asynctaskが再度終了しないように注意してください。

  • android:clearTaskOnLaunch属性を見て、trueに設定します。

    Google Docによると、この属性については次のとおりです。

    たとえば、誰かがホーム画面からアクティビティPを起動し、そこからアクティビティQに移動します。ユーザーは次にホームを押してからアクティビティPに戻ります。通常、ユーザーにはアクティビティQが表示されます。これが、最後のアクティビティであるためです。 Pのタスクでやっています。ただし、Pがこのフラグを「true」に設定した場合、ユーザーがHomeを押してタスクがバックグラウンドに移動すると、その上のすべてのアクティビティ(この場合はQ)が削除されます。したがって、ユーザーはタスクに戻るときにPのみを表示します。

    そして私はこれがあなたが望む正確なケースだと思います。

これにより、目的のタスクを実行するためのヒントが得られることを願っています。

于 2013-02-04T06:10:47.310 に答える
1

onPostExecutecのメソッドからアクションをブロードキャストreceiverし、aとbでそのアクションを受信するブロードキャストを登録できます。次に、そのレシーバーonReviceメソッドで終了します

c、AsyncTask、

 void onPostExecute(Long result) {
         ----
         Intent intent1 = new Intent("you custom action");
    context.sendBroadcast(intent1);
     }

aと_b

registerReceiver(new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {
                finish();

            }
        },new IntentFilter("you custom action"));
于 2013-02-04T06:09:54.323 に答える
1

個人的には、通知バーを使用してユーザーにクエリのステータスを通知します。

このようにして、未完成のアクティビティが発生するという問題全体を回避できます。また、ユーザーがまだ送信ボタンをクリックしていない場合にのみ、アクティビティを未完了のままにします。

于 2013-02-04T06:40:43.653 に答える
0

アクティビティが破棄される直前に呼び出されるAndroidマニュアル についてonDestroy()は、finishを呼び出すことができます(アクティビティを完全に強制終了する前にbgスレッドを停止することもできます)。

アクティビティが強制終了された場合、bgスレッドにも関心がないと想定できます。たとえば、bgスレッドが、完了する必要のあるイメージなどをダウンロードする場合は、asynctaskの代わりにserviceを使用する必要があります。

于 2013-02-04T06:09:09.290 に答える
0

破棄されたアクティビティを直接終了することはできないためfinish()、その中にあるだけですonCreate()( @Labeeb Pが提案)。方法は次のとおりです。

  1. 終了しようとしたときにアクティビティが既に破棄されている場合は、代わりにブール値のフラグをどこかに保存してください。

    if(activity != null)
    {
        // Activity object still valid, so finish() now.
        activity.finish();
    }
    else
    {
        // Activity is destroyed, so save a flag.
        is_activity_pending_finish = true;
    }
    
    • アプリが破棄されてもフラグを保持する必要がある場合は、永続ストレージを使用しますSharedPreferences( @Labeeb Pが推奨)。
  2. アクティビティのonCreate()で、フラグを確認して を呼び出しますfinish()

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
    
        if(is_activity_pending_finish)
        {
            is_activity_pending_finish = false; // Clear the flag.
    
            // This activity should have been finished, so finish it now.
            finish();
            return;
        }
    
        ...
    }
    
    • 同じ Activity クラスのインスタンスが複数ある場合、終了するアクティビティの特定のインスタンスを識別するために、ブール値フラグ以上の何かが必要になる場合があります。

ドキュメントに記載されているように、呼び出しfinish()onCreate()実際には正当な操作です。

...アクティビティを破棄するためにfinish()内部から呼び出すことができます。onCreate()この場合、システムonDestroy()は他のライフサイクル メソッドを呼び出さずにすぐに呼び出します。


その他の考慮事項:

  • 特にそれが唯一のアクティビティである場合、アプリがバックグラウンドにある間にアクティビティを終了することはお勧めできません。ユーザーを混乱させないように注意してください。
  • ユーザー エクスペリエンスを向上させるために、アプリがバックグラウンドで動作しているときにアクティビティを終了した場合は、ユーザーに通知することをお勧めします。トースト(短い通知に適しています) または通知(ユーザーが忘れている可能性のある長い操作に適しています) の使用を検討してください( @Stephan Branczykおよび@dilixが推奨)。

もちろん、アクティビティが破棄されても、アプリがバックグラウンドにあるとは限りません (別のフォアグラウンド アクティビティがある可能性があります)。それでも、上記の解決策 ( を呼び出す)finish()onCreate()機能します。

于 2013-02-05T02:35:53.263 に答える
0

システムがアクティビティを破棄しようとすると、 が呼び出されますonSaveInstanceState。ここで を呼び出すことができますfinish()。それでおしまい。

警告: 私はこれを試したことがないので、onSaveInstanceState からの finish() の呼び出しに問題があるかどうかはわかりません。これを試したら、コメントして、うまくいく方法を教えてください。

于 2014-10-22T20:07:02.683 に答える