New Intent() запускает новый экземпляр с Android: launchMode="singleTop"

У меня есть активность A с android:launchMode="singleTop" в манифесте.

Если я иду в активность B, C, а также D там у меня есть ярлыки меню, чтобы вернуться к рутинной активности моих приложений (A).

Код выглядит так:

Intent myIntent = new Intent(getBaseContext(), MainActivity.class);
startActivity(myIntent);

Однако вместо возврата к уже существующему экземпляру A из моего MainActivity.class это создает новый экземпляр -> это идет к onCreate() вместо onNewIntent(),

Это не ожидаемое поведение, верно?

6 ответов

Решение

Это должно сделать свое дело.

<activity ... android:launchMode="singleTop" />

Когда вы создаете намерение запустить приложение, используйте:

Intent intent= new Intent(context, YourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);

Это то, что должно быть нужно.

В конце концов, у меня получилось так:

Intent myIntent = new Intent(getBaseContext(), MainActivity.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(myIntent);

Цитата из документации:

"Стандартный" и "одиночный" режимы отличаются друг от друга только в одном отношении: каждый раз, когда появляется новое намерение для "стандартного" действия, создается новый экземпляр класса, чтобы ответить на это намерение. Каждый экземпляр обрабатывает одно намерение. Аналогичным образом, новый экземпляр действия "singleTop" также может быть создан для обработки нового намерения. Однако, если целевая задача уже имеет существующий экземпляр действия на вершине своего стека, этот экземпляр получит новое намерение (в вызове onNewIntent()); новый экземпляр не создан.

Я не уверен на 100%, что означает "уже есть существующий экземпляр действия наверху его стека", но, возможно, ваша деятельность не соответствует этому условию.

Было бы singleTask или же singleInstance работа для тебя? Или, возможно, вы могли бы попробовать установить FLAG_ACTIVITY_SINGLE_TOP на намерение, которое вы создаете, чтобы увидеть, если это имеет значение, хотя я не думаю, что это будет.

Вы можете вернуться к тому же существующему экземпляру Activity с помощьюandroid:launchMode="singleInstance"

в манифесте. Когда вы вернетесь к A от Bможет понадобиться finish() разрушать B,

Во-первых, структура стека может быть исследована. Для режима запуска:singleTop
Если экземпляр того же действия уже находится над стеком задач, этот экземпляр будет повторно использован для ответа на намерение.

Все действия удерживаются в стеке ("первым пришел последним"), поэтому, если ваша текущая активность находится на вершине стека и если вы определили ее в manifest.file как singleTop

android:name=".ActivityA"
android:launchMode="singleTop"

если вы в ActivityA воссоздаете действие, оно не будет введено, onCreate возобновит onNewIntent(), и вы можете увидеть это, создав уведомление Not: Если вы не реализуете onNewIntent(Intent), вы не получите новое намерение.

Intent activityMain = new Intent(ActivityA.this,
                        ActivityA.class);

                activityMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                startActivity(activityMain);




    @Override
        protected void onNewIntent(Intent intent) {

            super.onNewIntent(intent);

            notify("onNewIntent");
        }

        private void notify(String methodName) {

            String name = this.getClass().getName();
            String[] strings = name.split("\\.");

            Notification noti = new Notification.Builder(this)
                    .setContentTitle(methodName + "" + strings[strings.length - 1])
                    .setAutoCancel(true).setSmallIcon(R.drawable.ic_launcher)
                    .setContentText(name).build();
            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            notificationManager.notify((int) System.currentTimeMillis(), noti);

        }

Это связано с тем, что исходное действие A уже уничтожено к тому времени, когда вы запускаете его из B, C или D. Поэтому onCreate будет вызываться вместо onNewIntent(). Один из способов решения этой проблемы - всегда уничтожать существующую A(используя соединение FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK при startActivity) перед запуском новой A, поэтому всегда вызывается onCreate, и вы помещаете код onNewIntent () в onCreate, проверяя if getIntent() - это намерение, с которого вы начали.

Другие вопросы по тегам