Предотвратить восстановление стека активности?
Когда процесс приложения уничтожается, его стек активности сохраняется. Затем, когда приложение перезапускается, все мои действия возобновляются и запускаются с нулевыми указателями. Вместо того, чтобы изменять каждое действие, чтобы приспособить это событие, я бы просто запустил свое приложение с базовым действием, а не пытался воссоздать стек действий.
Это возможно?
Я знаю о Intent.FLAG_ACTIVITY_CLEAR_TOP, но, насколько я понимаю, это приведет к уничтожению действий только после их повторного создания.
РЕДАКТИРОВАТЬ: это ясно, TaskOnLaunch, что я хочу? Я добавил его к своей активности по умолчанию, но не вижу никакого эффекта. Но это убьет мою деятельность, даже если я просто сверну приложение, не так ли? Я бы предпочел только очистить стек, если весь процесс перезагружается.
РЕДАКТИРОВАТЬ 2: Нет, это не то, что я хочу - инженер Android дал подробный ответ на несколько вопросов о том, как использовать ClearTaskOnLaunch: http://groups.google.com/group/android-developers/browse_thread/thread/da024bcaf4e1960f/ab1e2b35c360cb65?pli=1
3 ответа
Единственное решение, которое мне удалось найти, - это проверить глобальную статическую переменную в каждом экземпляре onCreate() и завершить работу, если эта переменная была сброшена в ноль, указывая на то, что задача была перезапущена. Я закрываю все действия до своей основной активности и начинаю заново.
Скоро я надеюсь, что мое приложение будет в точке, где оно может сохранить необходимые значения в onPause(), но пока это единственный надежный способ работы с потерянной инициализацией...
Если вы работаете с spalshScreen или каким-либо другим LauncherActivity, вы можете создать глобальное статическое логическое значение и использовать его следующим образом:
сначала найдите способ сохранить эту статическую переменную (возможно, создайте глобальный файл 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 останется истинным. Даже если это так, это означает, что ваше приложение в настоящее время перезапускается, и для processkiled будет установлено значение true, а для всех переменных будут созданы экземпляры (No NullPointerException)
Создав свой собственный метод restartApp, вы получите то, что хотите:
(в каждом действии вы добавляете эти строки:)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Global.processKilled){
restartApp();
}
...//your code here
}
РЕДАКТИРОВАТЬ
если вы не являетесь глобальным переменным-аголиком, вы можете проверить, является ли значение savedInstanceState нулевым или нет...
Я использую этот кусок кода:
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);
}
}
Приведенное выше решение полагаться на смерть процесса для сброса статической переменной работает, но это запах кода из-за его зависимости от статического состояния. Вот решение, которое имеет очень похожие свойства, но не зависит от статической переменной, сбрасываемой после смерти процесса. Вместо этого он полагается на тот факт, что после остановки процесса для любых сохраненных фрагментов переменные экземпляра будут возвращены к значениям по умолчанию.
/**
* 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);
...
}
Это то, что нужно учитывать при работе с нативными инструментами Android, или это проблема, поднимаемая сторонними убийцами задач? По крайней мере, на эмуляторе, использующем "принудительную остановку", кажется, сбрасывается стек активности - это то, чего я ожидал всегда, когда приложение умирает.