防止活动堆栈被还原?

时间:2011-03-24 18:13:14

标签: android process android-activity kill activity-stack

当应用程序的进程被终止时,将保存其活动堆栈。然后,当重新启动应用程序时,我的所有活动都会恢复并运行为空指针。我宁愿让我的应用程序从基本活动开始而不是尝试重新创建活动堆栈,而不是修改每个活动以适应此事件。

这可能吗?

我知道Intent.FLAG_ACTIVITY_CLEAR_TOP,但据我所知,只会在重新创建后杀死活动。

编辑:clearTaskOnLaunch我想要的是什么?我已将其添加到我的默认活动中,但看不到任何效果。但即使我只是最小化应用程序,这也会扼杀我的活动,不是吗?如果整个过程重启,我宁愿只清除堆栈。

编辑2:不,这不是我想要的 - 一位Android工程师对如何使用ClearTaskOnLaunch的一些问题做出了彻底的回应:http://groups.google.com/group/android-developers/browse_thread/thread/da024bcaf4e1960f/ab1e2b35c360cb65?pli=1

5 个答案:

答案 0 :(得分:10)

我能找到的唯一解决方案是在onCreate()的每个实例中检查一个全局静态变量,并在该变量重置为null时完成,表明任务已重新启动。我将所有活动关闭到我的根活动并重新开始。

很快我希望我的应用程序可以在onPause()中保存所需的值,但是直到那时这才是我知道处理丢失初始化的唯一可靠方式......

答案 1 :(得分:2)

我使用这段代码:

public class NoRestoreActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Shoul be always NULL when created the first time, just in case...
        if (savedInstanceState != null && savedInstanceState.getInt("SavedInstance") > 0) {
            // ----- Your prefferred way to kill an application ----
            try {                
                this.finishActivity(0);               
            } catch (Exception ee) {
            }
            try {
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(10);
            } catch (Exception eeee) {
            }
            return;
        }
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onSaveInstanceState (Bundle outState){
        super.onSaveInstanceState(outState);
        outState.putInt("SavedInstance",1);
    }
}

答案 2 :(得分:1)

如果您使用的是spalshScreen或其他LauncherActivity,则可以创建一个Global静态布尔值并像这样使用它:

首先找到一种存储此静态变量的方法(也许创建一个全局Java文件)

public abstract class Global {
    ...
    public static boolean processKilled = true;
    ...
}

然后,在您的laucherActivity(MainActivity或Splashscreen ...)中添加以下行:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Global.processKilled = false;
        ...//your code here
    }

实际上,如果您的应用程序进程死了,则它肯定不会通过launcherActivity的代码。因此,静态布尔processKilled将保持为真。即使这样做,这也意味着您的应用当前正在重新启动,并且处理过程将被正确设置为true,并且所有变量都被实例化(没有NullPointerException)

通过创建自己的restartApp方法,您将获得所需的内容:

(在每个活动中,请添加以下行:)

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (Global.processKilled){
            restartApp();
        }
        ...//your code here
    }

编辑

如果您不是全局变量圆括号,则可能要检查一下saveInstanceState是否为null ...

答案 3 :(得分:0)

这是处理原生Android工具时应该考虑的问题,还是第三方任务杀手引发的问题?至少在模拟器上使用“强制停止”似乎重置了活动堆栈 - 这是我预计在应用程序死亡时总会发生的事情。

答案 4 :(得分:0)

上面依靠进程死亡来重置静态变量的解决方案是可行的,但是由于它依赖于静态,因此是一种代码气味。这是一种具有非常相似属性的解决方案,但不依赖于进程死亡后重置静态变量。取而代之的是,它依赖于这样一个事实:在进程终止后,所有保留的片段都将其实例变量设置回默认值。

/**
 * This retained fragment functions as a detector for when the activity is restoring it's state
 * after a process death.
 *
 * <p>The callback onRestoreInstanceState cannot be used here, since that callback is also invoked
 * during regular activity recreation due to configuration changes, and there's no way to tell
 * whether the state is being restored from a configuration change or from recreation after process
 * death.
 *
 * <p>This retained fragment can be used to disambiguate these two scenarios. When the fragment is
 * created, it's {@code wasProcessKilled} flag is set to {@code false}, which will be retained
 * across activity restarts from configuration changes. However, on process rebirth, the retained
 * fragment will still be retained, but the value of {@code wasProcessKilled} will be set back to
 * its default value of {@code true}.
 */
public class ProcessDeathDetectorFragment extends Fragment {

  public static final String TAG = "ProcessDeathDetectorFragmentTag";

  public static ProcessDeathDetectorFragment create() {
    ProcessDeathDetectorFragment frag = new ProcessDeathDetectorFragment();
    frag.wasProcessKilled = false;
    frag.setRetainInstance(true);
    return frag;
  }

  private boolean wasProcessKilled = true;

  public boolean wasProcessKilled() {
    return wasProcessKilled;
  }

  @VisibleForTesting
  public void clear() {
    wasProcessKilled = true;
  }
}




private void closeActivityIfRestoredAfterProcessDeath(Bundle bundle) {
  FragmentManager fragmentManager = getSupportFragmentManager();
  ProcessDeathDetectorFragment retainedFragment =
      (ProcessDeathDetectorFragment)
          fragmentManager.findFragmentByTag(ProcessDeathDetectorFragment.TAG);

  if (bundle != null && retainedFragment != null && retainedFragment.wasProcessKilled()) {
    // If the bundle is non-null, then this is a restore flow.
    // If we are in a restore flow AND the retained fragment's wasProcessKilled flag is set back
    // to its default value of true, then we are restoring
    // from process death, otherwise the flag would have the value of false that was set when it
    // was created for the first time.
    finish();
    return;
  }

  if (retainedFragment == null) {
    fragmentManager
        .beginTransaction()
        .add(ProcessDeathDetectorFragment.create(), ProcessDeathDetectorFragment.TAG)
        .commit();
  }
}

@Override
protected void onCreate(Bundle bundle) {
  super.onCreate(bundle);
  closeActivityIfRestoredAfterProcessDeath(bundle);
  ...
}