Как проверить, если активность все еще в стеке?
Какой лучший способ проверить, находится ли активность в стеке, чтобы перезвонить?
Intent i = new Intent(getApplicationContext(),MyClass.class);
startActivity(i);
3 ответа
Посмотрите на API ActivityManager
Чтобы получить экземпляр ActivityManager, используйте этот код:
ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
Я удивлен, насколько непопулярен этот (вид) вопрос (ы).
Позвольте мне начать с решения в первую очередь:
поскольку ActivityManager.getRunningTasks
устарела начиная с API 21,
Мы должны найти другой способ узнать, какие действия находятся в спине. И я понял, что мы действительно можем реализовать наш собственный "стек"!
Я объявил ArrayList в MyOwnApplication:
private ArrayList<Class> runningActivities = new ArrayList<>();
И добавил открытые методы для доступа и изменения этого списка:
public void addThisActivityToRunningActivityies (Class cls) {
if (!runningActivities.contains(cls)) runningActivities.add(cls);
}
public void removeThisActivityFromRunningActivities (Class cls) {
if (runningActivities.contains(cls)) runningActivities.remove(cls);
}
public boolean isActivityInBackStack (Class cls) {
return runningActivities.contains(cls);
}
В BaseActivity
где все виды деятельности расширяют его:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MyOwnApplication)getApplication()).addThisActivityToRunningActivityies(this.getClass());
}
@Override
protected void onDestroy() {
super.onDestroy();
((MyOwnApplication)getApplication()).removeThisActivityFromRunningActivities(this.getClass());
}
И тогда вы можете легко использовать isActivityInBackStack
Проверять.
ПОЧЕМУ ЭТО НЕОБХОДИМО?
Да, конечно, большинство случаев может быть сделано с использованием флагов намерения и правильной навигации.
Но есть такой вариант использования, который, я думаю, должен быть распространенным, что я не нахожу решение, просто используя намеренные флаги.
Предположим, у меня есть приложение, в котором есть навигационная панель почти во всех действиях.
Я перемещаюсь из MainActivity
в ActivityA
, а затем создал ChildActivityB
от ActivityA
, Обратите внимание, что ActivityA
не является родителем ChildActivityB
поскольку ChildActivityB
может быть открыт из других действий, таких как уведомление.
Обратите внимание, что, ChildActivityB
также есть ящик. Я могу перейти к ActivityA
через ящик, вместо нажатия кнопки вверх или назад. Теперь представьте, что вы проходите через такой процесс: Действие A -> ChildActivity B -> Drawer -> Действие A -> ChildActivityB -> Drawer -> Действие A..... В backstack будут созданы бесконечные действия.
Чтобы исправить такое поведение, нам нужно использовать Intent Flags:
(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);
Все идет нормально. Тем не менее, у меня есть пользовательские анимации перехода активности с помощью overridePendingTransition()
, Я заметил, что если я поставлю вышеупомянутые флаги намерения вместе с overridePendingTransition()
, в анимации будет сбой, потому что активность уничтожается в середине анимации из-за флага Intent.FLAG_ACTIVITY_CLEAR_TOP
,
Теперь, если я смогу определить, ActivityA
в backstack или нет, поведение будет идеальным:
private void navigateToDrawerItems(Class cls) {
drawerLayout.closeDrawer(GravityCompat.END);
Intent intent = new Intent(this, cls);
if (((MyOwnApplication)getApplication()).isActivityInBackStack(cls)) {
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
} else {
startActivity(intent);
overridePendingTransition(R.anim.slide_right_in, R.anim.slide_left_out);
}
}
Вы можете переключать глобальную переменную как индикатор внутри onCreate()
а также onDestory()
определенного класса, ИЛИ внутри onActivityCreated()
а также onActivityDestroyed()
ActivityLifecycleCallbacks.
например:
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
if (activity instanceof YourActivity) {
myGlobalData.setActExist(true);
}
}
@Override
public void onActivityDestroyed(Activity activity) {
if (activity instanceof YourActivity) {
myGlobalData.setActExist(false);
}
}
});