Урок 91. AsyncTask. Поворот экрана

Обсуждение уроков
Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Урок 91. AsyncTask. Поворот экрана

Сообщение damager82 » 27 июн 2012, 23:00

В этом уроке:
- сохраняем связь с AsyncTask при повороте экрана


Click here to read this article!
Последний раз редактировалось damager82 22 май 2017, 23:40, всего редактировалось 6 раз.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

chivorotkiv
Сообщения: 4
Зарегистрирован: 29 июн 2012, 03:14

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение chivorotkiv » 01 июл 2012, 03:30

Привет.

onRetainNonConfigurationInstance - это классный метод. Но не правильнее ли для продолжения АсинкТасков использовать настройки активити: android:configChanges="keyboardHidden|orientation"?

Аватара пользователя
KamiSempai
Сообщения: 1339
Зарегистрирован: 17 фев 2012, 21:23
Откуда: Мордор

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение KamiSempai » 01 июл 2012, 10:27

chivorotkiv писал(а):android:configChanges="keyboardHidden|orientation"?
Можно, только если Вы не используете разные разметки для разных ориентаций экрана.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

Gorets
Сообщения: 8
Зарегистрирован: 12 янв 2012, 12:38

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение Gorets » 02 июл 2012, 16:04

Спасибо за урок =)

chivorotkiv
Сообщения: 4
Зарегистрирован: 29 июн 2012, 03:14

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение chivorotkiv » 05 июл 2012, 17:51

KamiSempai писал(а):
chivorotkiv писал(а):android:configChanges="keyboardHidden|orientation"?
Можно, только если Вы не используете разные разметки для разных ориентаций экрана.
Если я использую разные разметки для разных ориентаций экрана, то задаю новую разметку в методе onConfigurationChanged. При этом onCreate не вызывается, активити продолжает жить своей жизнью.

math64
Сообщения: 235
Зарегистрирован: 16 июл 2012, 07:47

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение math64 » 16 июл 2012, 11:51

Если onProgressUpdate() произойдет во время поворота экрана, будет нехорошо (или вызов этого метода будет отложен до завершения поворота экрана?).
В любом случае, лучше в onProgressUpdate() добавить проверку activity != null, а в link и unlink - synchronized.

Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение damager82 » 17 июл 2012, 11:13

Да, проверка activity != null точно не будет лишней, иначе можно нарваться на NullPoniterException.
А synchronized для link и unlink зачем? synchronized защищает метод от одновременного запуска, а у нас тут все последовательно - старое Activity отпустило, новое приняло.

В течение дня немного дополню урок. Попробую написать решение проблемы.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение AndreyI » 18 июл 2012, 00:18

В общем, если я правильно понял, благодаря Діма и коллективному разуму эту задачу можно решить еще проще:
Достаточно объявить поля mt и tv как static, они станут объектами класса и все будет работать.
Разумеется нужно добавить проверку, чтоб задача не перезапускалась в onCreate, если она уже существует и выполняется.

Аватара пользователя
IlyaZh
Сообщения: 32
Зарегистрирован: 14 июл 2012, 09:52
Откуда: Санкт-Петербург
Контактная информация:

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение IlyaZh » 19 июл 2012, 10:02

Здравствуйте. Подскажите пожалуйста. Внутри AsycnTask у меня есть следующий блок кода.

Код: Выделить всё

@Override
    	protected void onPreExecute() {
    		pd = ProgressDialog.show(MainActivity.this, getResources().getString(R.string.app_name), "Выполняется загрузка данных", true, true);
            pd.setOnCancelListener(new OnCancelListener() {
                public void onCancel(DialogInterface dialog) {
                    LoadDataTask.this.cancel(true);
                }
            }); 
    		super.onPreExecute();
    	}
Так вот, если прописать static к Async, то среда ругается на ссылку на ресурсы и на то, что я MainActivity заменяю на activity. Иначе при повороте экрана приложение внезапно завершает свою работу, когда диалоговое окно должно закрыться методом onPostExecute().

Подскажите пожалуйста, как можно решить такую проблему?

Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение damager82 » 19 июл 2012, 13:05

IlyaZh писал(а):Так вот, если прописать static к Async, то среда ругается на ссылку на ресурсы и на то, что я MainActivity заменяю на activity.
Странно. Может не корректно заменяете?
Так должно работать:

Код: Выделить всё

pd = ProgressDialog.show(activity, activity.getResources().getString(R.string.app_name), "Выполняется загрузка данных", true, true);
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

Аватара пользователя
IlyaZh
Сообщения: 32
Зарегистрирован: 14 июл 2012, 09:52
Откуда: Санкт-Петербург
Контактная информация:

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение IlyaZh » 19 июл 2012, 13:25

Помогло, спасибо!
Но теперь ещё проблемка.
В коде

Код: Выделить всё

		@Override
		protected Void doInBackground(Void... params) {
			//boolean result = true;
			// Загружаем данные о точках
			try {
		        loadPoints();
			} catch (Exception e) {
	                Log.e(DEBUG_TAG, "Unexpected failure in XML downloading and parsing", e);
	        }
			return null;
		}
		
У меня загружается функция loadPoints(), где идёт парсинг xml данных с помощью xmlpullparser. А затем спарсенные данные отправляются в другую функцию, в которой xml разбирается и на яндекс карту выводятся точки, используя данные из xml - так вот эту функцию нельзя делать статик, ибо тогда ругается на указание "this" в такой конструкции balloon.setOnBallonListener(this);

Как здесь можно поступить? Или где можно почитать подробнее про вынос async за пределы текущей активности..
Или как можно разделить парсинг и разбор?? Сохранять xml данные на sd карту не очень хочется.

Или сделать передачу параметра activiy в каждую из дочерне вызываемых функций?

math64
Сообщения: 235
Зарегистрирован: 16 июл 2012, 07:47

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение math64 » 19 июл 2012, 17:20

Нe заменяйте вложенный класс вручную.
(Перед рефакторингом сохраните проект для возможного отката)
Если класс анонимный, выполните рефакторинг Refactor/Convert Anonimous Class to Nested...
Затем
Refactor/Move Type to New File...
(Почему-то нет отдельного рефакторинга для конвертации вложенного класса в обычный)

После рефакторинга можут быть ошибки, если Эклипс не смог переделать некоторые конструкции автоматически.
В случае чего, вернитесь к старой версии.

Wa1deMar
Сообщения: 14
Зарегистрирован: 01 авг 2012, 11:19

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение Wa1deMar » 01 авг 2012, 11:26

damager82 писал(а):Есть еще один способ (кроме static) избежать связки AsyncTask и Activity - просто сделайте ваш класс, наследующий AsyncTask, не внутренним, а отдельно от MainActivity
Тоесть, если сделать отдельный клас то он не будет заново пересоздаваться и не нужно играться с ссылками?

Аватара пользователя
Finch
Сообщения: 439
Зарегистрирован: 16 июл 2012, 21:37

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение Finch » 01 авг 2012, 13:25

Wa1deMar писал(а):
damager82 писал(а):Есть еще один способ (кроме static) избежать связки AsyncTask и Activity - просто сделайте ваш класс, наследующий AsyncTask, не внутренним, а отдельно от MainActivity
Тоесть, если сделать отдельный клас то он не будет заново пересоздаваться и не нужно играться с ссылками?

Не совсем понял, ну да ладно, всё просто как веник

Имеем отдельный класс унаследованный от асинктаска, что6 его вызвать те6е в лю6ом случае нужно создать экземпляр класса

Код: Выделить всё

MyClass my = new MyClass(конструктор);
в каждой своей активити ты можешь делать новые экземпляры(не зависящие друг от друга), тут всё зависит на сколько твой асинктаск 6удет универсален для выполнения поставленной задачи в конкретной активити =)
CEO of a company R.id.team

Paul
Сообщения: 1
Зарегистрирован: 17 авг 2012, 12:24

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение Paul » 17 авг 2012, 12:29

Есть еще одна маленькая особенность.
После того как наш textView принял конечное значение и при повороте экрана, layout присваивается первоначальное состояние. Как решение, сохранить результат в переменную и проверять в onCreate на null.

ilsy
Сообщения: 1
Зарегистрирован: 11 апр 2012, 15:51

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение ilsy » 06 ноя 2012, 19:04

Как я понял android:configChanges="keyboardHidden|orientation" используется как лёгкая "заглушка", при которой всё работает, до тех пор пока кто-то не позвонит или типо того.

Но мучает вопрос, почему вы не использовали для сохранения связку onSaveInstanceState(Bundle outState)/onRestoreInstanceState(Bundle) ?

gera
Сообщения: 9
Зарегистрирован: 11 окт 2012, 23:30

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение gera » 15 дек 2012, 01:48

Есть еще один способ (кроме static) избежать связки AsyncTask и Activity - просто сделайте ваш класс, наследующий AsyncTask, не внутренним, а отдельно от MainActivity.
не пойму зачем мы добавили static или зачем класс делать не внутренним.
ведь работает внутренний класс как со static так и без...

Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение damager82 » 18 дек 2012, 09:57

gera писал(а):
Есть еще один способ (кроме static) избежать связки AsyncTask и Activity - просто сделайте ваш класс, наследующий AsyncTask, не внутренним, а отдельно от MainActivity.
не пойму зачем мы добавили static или зачем класс делать не внутренним.
ведь работает внутренний класс как со static так и без...
Внутренний класс держит ссылку на внешний класс, т.е. на старое никому после поворота экрана не нужное Activity. Держит ссылку, значит держит в памяти. А зачем держать в памяти ненужный объект?

Атрибут static избавляет внутренний класс от этой ссылки.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

3Gern
Сообщения: 25
Зарегистрирован: 30 июл 2012, 13:32

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение 3Gern » 22 дек 2012, 19:18

Делаю по примеру парсинг страницы, но при повороте все равно создается новое активити, может из-за того что передаю ссылку в execute?

Код: Выделить всё

@Override
	protected void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		if (parse != null)
		{
                parse = (Parse) getLastNonConfigurationInstance();
		}
                else
                {
                parse = new Parse();
		parse.execute(URL);
		} 
	}

gera
Сообщения: 9
Зарегистрирован: 11 окт 2012, 23:30

Re: Урок 91. AsyncTask. Поворот экрана

Сообщение gera » 23 дек 2012, 01:02

Проверяй что вернет getLastNonConfigurationInstance(). Если вернет null, то создай новый объект parse = new Parse().
Если бы ты внимательно читал урок, то заметил бы этот код

Код: Выделить всё

mt = (MyTask) getLastNonConfigurationInstance();
if (mt == null) {
   mt = new MyTask();
   mt.execute();
}

Ответить