如何完成销毁活动

时间:2013-02-04 05:36:21

标签: android android-activity activity-lifecycle

据我了解,销毁的活动并不等同于已完成的活动

  • 完成
    • 活动已从back stack
    • 中移除
    • 它可以由程序触发(例如通过调用finish()),或者由用户按后退键(隐式调用finish())。
    • 完成一项活动会破坏它。
  • 销毁
    • Android操作系统可能会破坏不可见的活动以恢复内存。当用户导航回活动时,将重新创建活动。
    • 当用户旋转屏幕时,活动将被销毁并重新创建。
    • 参考:Recreating an Activity

所以如何完成销毁的活动finish()方法需要Activity对象,但如果活动被销毁,我没有Activity对象 - 我不应该持有对被破坏活动的引用,是吗?


案例研究:

我有一个a活动,启动b,然后启动c(使用Activity.startActivity()),现在back stack为:< / p>

a → b → c

c中,用户填写表单并点按“提交”按钮。使用AsyncTask向远程服务器发出网络请求。任务完成后,我会显示toast并通过调用c.finish()完成活动。完美。

现在考虑这种情况:

当异步任务正在进行时,用户切换到另一个应用程序。然后,由于内存限制,Android操作系统决定销毁所有3项活动(abc)。之后,异步任务完成。现在我该如何完成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:从Activity上下文外部调用startActivity()需要FLAG_ACTIVITY_NEW_TASK标志。这真的是你想要的吗?

编辑: 澄清:我需要等到异步任务完成,然后根据服务器确定是否完成c响应。

6 个答案:

答案 0 :(得分:2)

  

android.util.AndroidRuntimeException:从中调用startActivity()   在Activity上下文之外需要FLAG_ACTIVITY_NEW_TASK   旗。这真的是你想要的吗?

  • 当您从中启动活动时,会发生此异常 后台线程或服务。你需要通过
    只要您需要“发射器”,FLAG_ACTIVITY_NEW_TASK就会标记 行为类型。

    • 只需添加mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);即可避免此异常。

  • 不推荐您尝试杀死活动的方式,让我们 android处理自己。完成一项活动没有任何意义 已被销毁。

现在,您可以做什么?

  • 如果您在应用程序不在前台时遇到完成活动的问题,您可以做的是实施安全检查,只有当应用程序在前台进行后台堆栈活动时才会完成活动或否则就跳过这一步。

  • 我认为你正试图在应用程序处于后台时终止活动。这样做似乎有点困难,但您可以使用onUserLeaveHint来确定应用程序何时在后台运行以完成活动,或者您可以通过添加finish();来完成活动在onStop()。只要确保asynctask的onPost()没有按顺序再次完成它以避免异常。

  • 查看android:clearTaskOnLaunch属性并将其设置为true。

    Google Doc说这个属性是:

      

    例如,有人从主屏幕启动活动P,   从那里开始活动Q.用户接下来按Home,然后   然后返回活动P.通常,用户会看到活动Q,   因为这是他们最后在P的任务中所做的事情。但是,如果P设定   这个标志为“true”,所有活动都在它之上(Q在此   当用户按下Home并且任务转到了   背景。因此用户在返回任务时只看到P.

    我认为这是你想要的确切案例。

希望这会给你一些提示,以实现你想要的任务。

答案 1 :(得分:1)

您可以使用c中的onPostExecute方法广播您的操作,并在a和b中注册广播receiver以接收该操作。然后在接收器onRevice方法

中完成

c,AsyncTask,

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

ab

registerReceiver(new BroadcastReceiver() {

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

            }
        },new IntentFilter("you custom action"));

答案 2 :(得分:1)

就个人而言,我会使用通知栏通知用户他的查询状态。

这样,我就可以避免完成一项未完成的活动。只有当用户还没有点击提交按钮时,我才会保持活动未完成。

答案 3 :(得分:0)

关于在活动被销毁之前调用的android manual onDestroy(),所以你可以在其中调用finish(即使你可以在完全杀死活动之前停止你的bg线程)。

我们可以假设,如果活动被杀死,我们也不会对bg线程感兴趣,例如,如果bg线程要下载需要完成的图像或者等等 - 所以你必须使用服务而不是asynctask。< / p>

答案 4 :(得分: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类的多个实例,则可能需要多个布尔标志来标识要完成的特定活动实例。

  3. finish()中调用onCreate()实际上是一项有效的操作,正如the doc中提到的那样:

      

    ...您可以从finish()内拨打onCreate()来销毁活动。在这种情况下,系统会立即调用onDestroy()而不调用任何其他生命周期方法。


    其他考虑因素:

    • 在应用处于后台时完成某项活动可能不是一个好主意,特别是如果它是唯一的活动。确保不要混淆用户。
    • 为了获得更好的用户体验,如果您在应用处于后台时完成某项活动,则可能需要通知用户。请考虑使用toasts(适用于简短通知)或notifications(适用于用户可能忘记的长时间操作)(由@Stephan Branczyk@dilix建议)。

    当然,被破坏的活动并不一定意味着应用程序处于后台(可能还有其他前台活动)。不过,上述解决方案(在finish()中调用onCreate())仍可正常工作。

答案 5 :(得分:0)

当系统试图销毁您的活动时,它会调用onSaveInstanceState。在这里,您可以致电finish()。那就是它。

警告:我从未尝试过此操作,因此我不确定是否存在从onSaveInstanceState调用finish()的任何问题。如果你试试这个,请发表评论,让我知道它是如何运作的。