Медленные функции в Android
Подскажите как вызывать функции работающие продолжительное время. Например: для реализации окна авторизации, когда после нажатия кнопки "Login" программа может надолго зависнуть посылая запрос через интернет.
Подскажите как вызывать функции работающие продолжительное время. Например: для реализации окна авторизации, когда после нажатия кнопки "Login" программа может надолго зависнуть посылая запрос через интернет.
Все операции , занимающие продолжительное время : загрузка/отправка по сети , обработка данных , сложные вычисления и пр. с длительностью более 5 секунд ( а на самом деле все , что хоть как то способно замедлить интерфейс ) , должно быть вынесено из основного (графического) потока в асинхронные .
Андроид имеет собственную реализацию организации асинхронных потоков , которая позволяет эффективно взаимодействовать с основным (графическим) потоком , так как обращения напрямую к UI из других потоков невозможно . Это класс AsyncTask
.
При реализации этого класса необходимо переопределить четыре метода:
doInBackground()
- собственно здесь размещается код , который должен выполняться в асинхронном потоке.Он не имеет доступа к UI-потоку.
Следующие три метода , служат для взаимодействия с UI-потоком:
onPreExecute()
– выполняется перед doInBackground()
onPostExecute()
– выполняется после doInBackground()
onProgressUpdate()
- выполняется в процессе выполнения асинхронной задачи. Здесь можно показывать промежуточные результаты , прогрессбар и тп.
Так же класс AsyncTask
, естественно , может принимать параметры на обработку и возвращать обработанные данные .
Другим способом организации многопоточности в Android является классическая реализация Java - класс Thread
для собственно открытия потока и класс Handler
для его взаимодействия с главным (графическим) потоком.
Оба эти способа имеют некоторые ограничения , как то очередь на выполнение следующего потока , что иногда несколько усложняет практическое использование этих инструментов , так как потоки при открытии встают в очередь и ожидают , пока тот , что был запущен ранее не закончит работу .
Для организации "истинной многозадачности" необходимо использовать вместо вызова execute
, вызов потока через executeOnExecutor
, который не связан никакими ограничениями .
// обычный вызов
new MyAsyncTask().execute();
//выполнение нескольких задач последовательно:
new MyAsyncTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
new MyAsyncTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
//выполнение нескольких задач паралельно:
new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
Так же в андроид есть более специализированные классы , выполняющие асинхронные задачи , например CursorLoader
который асинхронно загружает курсор выборкой из БД и дополнительно управляет жизненным циклом курсора .
Если вы будете пытаться выполнять сетевые операции (работа с интернет) в главном потоке , то начиная с android 3.0 получите экзепшен
android.os.NetworkOnMainThreadException
, который не даст вам заниматься таким безобразием . Начиная с Honeycomb все сетевые операции должны выполняться только в дополнительном потоке и никак иначе.
Дополнительное чтение:
Оффициальная документация андроид по асинхронным потокам.
Пример работы с AsyncTask
.
Пример работы с Thread
в Андроид.
Что за проблемы с потоками в Андроид