launchMode="singleTask" НЕ РАБОТАЕТ?!

Activity Lifecycle, Saving Activity State, Managing Tasks, Intent, Intent Filter
Ответить
Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

launchMode="singleTask" НЕ РАБОТАЕТ?!

Сообщение Mikhail_dev » 24 окт 2013, 13:59

Может я чего понять не могу, но:
"singleTask"
The system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its onNewIntent() method, rather than creating a new instance. Only one instance of the activity can exist at a time.
Немного вольного перевода с хабра
singleTask — создает новый таск и устанавливает Activity корнeвой для него, но только в случаи, если экземпляра данной Activity нет ни в одном другом таске. Если Activity уже расположена в каком либо таске, то откроется именно тот экземпляр и вызовется метод onNewIntent(). Она в свое время становится главной, и все верхние экземпляры удаляются, если они есть. Только один экземпляр такой Activity может существовать
Другими словами, у нас ВСЕГДА должна существовать ОДНА активность, у которой стоит флаг singleTask. Все активности, что будут выше по таску, должны будут уничтожены (это логично, потому как у нас тут стек, который позволяет достать что-то с середины лишь убрав всё сверху (LIFO)).
Картинка в тему
Изображение
В итоге, я получаю полную фигню при работе. Алгоритм действий у меня такой:
Активности: (А имеет singleTask) А>B>C>A>B>C>A (в два круга покажу, там интересно)
В итоге в таске получаем следующее:
1.
10-24 14:34:11.380 7294-7294/ru.lab_m.testtask D/sample﹕ ------------------
10-24 14:34:11.380 7294-7294/ru.lab_m.testtask D/sample﹕ Count: 1
10-24 14:34:11.390 7294-7294/ru.lab_m.testtask D/sample﹕ Root: ru.lab_m.testtask/.A
10-24 14:34:11.390 7294-7294/ru.lab_m.testtask D/sample﹕ Top: ru.lab_m.testtask/.A
10-24 14:34:14.950 7294-7294/ru.lab_m.testtask D/sample﹕ ------------------
10-24 14:34:14.950 7294-7294/ru.lab_m.testtask D/sample﹕ Count: 2
10-24 14:34:14.950 7294-7294/ru.lab_m.testtask D/sample﹕ Root: ru.lab_m.testtask/.A
10-24 14:34:14.950 7294-7294/ru.lab_m.testtask D/sample﹕ Top: ru.lab_m.testtask/.B
10-24 14:34:15.570 7294-7294/ru.lab_m.testtask D/sample﹕ ------------------
10-24 14:34:15.570 7294-7294/ru.lab_m.testtask D/sample﹕ Count: 3
10-24 14:34:15.570 7294-7294/ru.lab_m.testtask D/sample﹕ Root: ru.lab_m.testtask/.A
10-24 14:34:15.570 7294-7294/ru.lab_m.testtask D/sample﹕ Top: ru.lab_m.testtask/.C
10-24 14:34:16.380 7294-7294/ru.lab_m.testtask D/sample﹕ ------------------
10-24 14:34:16.380 7294-7294/ru.lab_m.testtask D/sample﹕ Count: 2
10-24 14:34:16.380 7294-7294/ru.lab_m.testtask D/sample﹕ Root: ru.lab_m.testtask/.A
10-24 14:34:16.380 7294-7294/ru.lab_m.testtask D/sample﹕ Top: ru.lab_m.testtask/.C
10-24 14:36:51.280 7294-7294/ru.lab_m.testtask D/sample﹕ ------------------
10-24 14:36:51.280 7294-7294/ru.lab_m.testtask D/sample﹕ Count: 2
10-24 14:36:51.280 7294-7294/ru.lab_m.testtask D/sample﹕ Root: ru.lab_m.testtask/.A
10-24 14:36:51.280 7294-7294/ru.lab_m.testtask D/sample﹕ Top: ru.lab_m.testtask/.B
10-24 14:36:52.310 7294-7294/ru.lab_m.testtask D/sample﹕ ------------------
10-24 14:36:52.310 7294-7294/ru.lab_m.testtask D/sample﹕ Count: 3
10-24 14:36:52.310 7294-7294/ru.lab_m.testtask D/sample﹕ Root: ru.lab_m.testtask/.A
10-24 14:36:52.310 7294-7294/ru.lab_m.testtask D/sample﹕ Top: ru.lab_m.testtask/.C
10-24 14:36:54.970 7294-7294/ru.lab_m.testtask D/sample﹕ ------------------
10-24 14:36:54.970 7294-7294/ru.lab_m.testtask D/sample﹕ Count: 2
10-24 14:36:54.970 7294-7294/ru.lab_m.testtask D/sample﹕ Root: ru.lab_m.testtask/.A
10-24 14:36:54.970 7294-7294/ru.lab_m.testtask D/sample﹕ Top: ru.lab_m.testtask/.C
(Использующийся код с одного из уроков)
[syntax=java5] final String LOG_TAG = "sample";
List<ActivityManager.RunningTaskInfo> list;
ActivityManager am;
public void showTask() {
am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
list = am.getRunningTasks(10);
for (ActivityManager.RunningTaskInfo task : list) {
if (task.baseActivity.flattenToShortString().startsWith("ru.lab_m")) {
Log.d(LOG_TAG, "------------------");
Log.d(LOG_TAG, "Count: " + task.numActivities);
Log.d(LOG_TAG, "Root: " + task.baseActivity.flattenToShortString());
Log.d(LOG_TAG, "Top: " + task.topActivity.flattenToShortString());
}
}
}[/syntax]
В итоге получается, что при переходе к A с C, должна оставаться ТОЛЬКО одна активность, а другие должны уничтожиться, но получается совершенно непонятная картина:
1. количество живущих активностей остается 2
2. Остались жить только крайние, хотя это нереально (LIFO)
3. Пишет что сейчас активность C в топе, а показывает мне на экране A.

2.
Но не в этом вся беда. Беда в том, что находясь в любой активности, при сворачивании (onPause(), onStop()) и разворачивании (onStart, onResume()), мы увидим активность, которая содержит флаг singleTask, т.е. А. Неважно в какой активности мы находимся, все другие выгрузятся.
В итоге получается вообще полная неразбериха.
А что собственно хотелось: Есть активность для входа, есть главная активность, есть активность с настройками. Итого 3. Первая - является главной. Третья должна уметь возвращаться к первой, причем так, что первая опять становилась единственной, дабы по кнопке назад мы не перешли на третью. Вот и всё что хотелось.
Требования: noHistory использовать нельзя, потому как он при блокировке экрана (onPause, onStop) уничтожает все активности, что стоят с этим флагом. Флаг FLAG_ACTIVITY_CLEAR_TASK использовать нельзя (он идет с API>=11, да и не работает он всё равно).

Я даже почти уверен, что никто не ответит на сей пост, но может лет так через дцать кто-нибудь найдет его и найдет себе помощь в решении: а решение тут тривиальное, но не особо красивое: запускать активности через startActivityForResult, после чего закрывать их через this.finish(), читая код который нам возвращается.
Такие вот дела. Тчк.

Аватара пользователя
anber
Сообщения: 584
Зарегистрирован: 10 июн 2013, 15:05
Откуда: UA

Re: launchMode="singleTask" НЕ РАБОТАЕТ?!

Сообщение anber » 24 окт 2013, 15:43

К сожалению сейчас нет времени вчитаться в вопрос, выхватил глазами только этот кусочек:
"Беда в том, что находясь в любой активности, при сворачивании (onPause(), onStop()) и разворачивании (onStart, onResume()), мы увидим активность, которая содержит флаг singleTask, т.е. А"
Посмотри этот вопрос, может найдешь там ответ:
http://stackoverflow.com/questions/2417 ... -preserved

UPD: В чем картинка сделана?
Личные сообщения с просьбой ответить на форуме или написать программу я просто удаляю, если я в хорошем настроении. Если в плохом добавляю автора в черный список. По любым другим вопросам feel free to write to me.

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: launchMode="singleTask" НЕ РАБОТАЕТ?!

Сообщение Mikhail_dev » 25 окт 2013, 09:40

anber, спасибо! Это помогло решить нетривиальную проблему.
Мне даже мысль не приходила, что такое поведения singleTask может быть очевидным. Однако почитав сейчас по ссылке, я всё равно не понял до конца, что происходит с тем Intent, что бросает андроид
{act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]flag=FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_IF_NEEDED cmp=A}
Я не пойму, он всё время новый Task создает?
В общем помогло
FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP
UPD: В чем картинка сделана?
В android.developer.com =)

Ответить