Android studio handler остановить

Класс Handler

Класс android.os.Handler является дальнейшим развитием потоков, упрощающий код. Handler может использоваться для планирования выполнения кода в некоторый момент в будущем. Также класс может использоваться для передачи кода, который должен выполняться в другом программном потоке.

Рассмотрим максимально простой пример для знакомства

Запустите пример на эмуляторе и через некоторое время закройте его через кнопку Назад или Домой. При этом смотрите на логи на вкладе Android Monitor. Вы увидите, что приложение по-прежнему печатает текст типа после секундной задержки после запуска.

Разберёмся, что происходит и как следует читать код.

Мы объявили новый объект Handler и булевую переменную, которая по умолчанию имеет значение false — по ней будем отслеживать состояние приложения. В третьей переменной мы сохраним текущее время в момент запуска.

Приложение запустилось, сразу же запоминаем время через currentTimeMillis() — это опорная точка отсчёта.

Основная логика заключена в условии if — тут пишется то, что мы хотим поместить в новый поток. Не страшно, если не понятно, как это всё работает. Просто уясните принцип. Мы иницилизируем объект mHandler и сразу начинаем его настраивать. Переопредляем его главный метод handleMessage() и вызываем метод суперкласса. Это ничем не отличается от вызова onCreate() активности, мы не раз такое делали.

Блок if позволяет управлять кодом для потока. Сам запуск мы сделаем позже. А в самом блоке мы снова получаем текущее время и сравниваем с самой первым временем, полученным во время запуска. Для удобства вычисления идут в секундах. Результат выводится в лог. Метод sendEmptyMessageDelayed() сообщает системе, что мы хотим повторять код в handleMessage() раз в секунду.

После инициализации и настройки mHandler мы присваиваем значение true переменной gameOn, показывая готовность к запуску кода из блока if.

Последняя строка sendEmptyMessage() запускает поток.

Можно использовать более сложные приёмы запуска потока, но пока этого достаточно для понимания.

Периодическое выполнение задачи

При сложных вычислениях может понадобиться очередь Runnable-объектов. Помещая объект в очередь, вы можете задать время его запуска. Для демонстрации использования обработчика потока напишем программу, запускающую фоновый процесс, который будет каждые 200 миллисекунд получать текущее время и обновлять текст. Нам понадобится кнопка Пуск и две текстовые метки, в которых будет отображаться время и количество нажатий кнопки:

На экране будет отображаться время и одновременно мы можем нажимать на кнопку. Эти действия не мешают друг другу, так как работают в разных потоках.

Кроме метода postDelayed() вы можете использовать метод postAtTime():

В этом случае объект r добавляется в очередь сообщений, запуск объекта производится во время, заданное вторым параметром.

Самый простой способ помещения объекта в очередь — метод post(), когда указывается только помещаемый объект без указания времени выполнения объекта:

Пример с индикатором прогресса

Всё, что вам нужно — создать экземпляр класса Handler в классе активности. Поток будет работать с объектом Handler, который в свою очередь, будет обновлять шкалу индикатора в основном потоке активности.

Чтобы послать сообщение в объект Handler, сначала необходимо вызвать метод obtainMessage(), чтобы извлечь объект Message из глобального пула сообщений.

Для вставки сообщения в очередь сообщений объекта Handler существует несколько методов:

  • sendMessage() — помещает сообщение в очередь немедленно (в конец очереди)
  • sendMessageAtFrontofQueue() — помещает сообщение в очередь немедленно и, кроме того, помещает это сообщение впереди очереди (по умолчанию оно ставится в конец очереди), таким образом ваше сообщение берет приоритет над всеми другими
  • sendMessageAtTime() — помещает сообщение в очередь в установленное время в миллисекундах
  • sendMessageDeiayed() — помещает сообщение в очередь после задержки, выраженной в миллисекундах
Читайте также:  Как очистить кэш клавиатуры андроид

Чтобы обрабатывать эти сообщения, для объекта Handler необходимо реализовать метод обратного вызова handleMessage(), который будет вызываться каждым сообщением из очереди сообщения.

Для примера создадим приложение с ProgressBar, который будет отображать ход выполнения длительной задачи (это будет простой цикл с приостановкой потока на 1 секунду в каждой итерации цикла) и обновлять степень завершения этой задачи через объект Handler в классе активности.

Splash-screen

Очень часто программисты используют Handler для реализации окна приветствия, которое автоматически закрывается и следом запускается основная активность игры или приложения.

Источник

Потоки

Потоки позволяют выполнять несколько задач одновременно, не мешая друг другу, что даёт возможность эффективно использовать системные ресурсы. Потоки используются в тех случаях, когда одно долгоиграющее действие не должно мешать другим действиям. Например, у нас есть музыкальный проигрыватель с кнопками воспроизведения и паузы. Если вы нажимаете кнопку воспроизведения и у вас запускается музыкальный файл в отдельном потоке, то вы не можете нажать на кнопку паузы, пока файл не воспроизведётся полностью. С помощью потоков вы можете обойти данное ограничение.

Использование фоновых потоков

Чтобы быть уверенным, что ваше приложение не теряет отзывчивости, хорошим решением станет перемещение всех медленных, трудоёмких операций из главного потока приложения в дочерний.

Применение фоновых потоков — необходимое условие, если вы хотите избежать появления диалогового окна для принудительного закрытия приложения. Когда активность в Android на протяжении 5 секунд не отвечает на события пользовательского ввода (например, нажатие кнопки) или приёмник широковещательных намерений не завершает работу обработчика onReceive() в течение 10 секунд, считается, что приложение зависло. Подобные ситуации следует избегать любой ценой. Используйте фоновые потоки для всех трудоёмких операций, включая работу с файлами, сетевые запросы, транзакции в базах данных и сложные вычисления.

Android предоставляет несколько механизмов перемещения функциональности в фоновый режим.

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDelayed(Runnable, long)
  • Handlers
  • AsyncTask

Класс AsyncTask позволяет определить операции, которые будут выполняться в фоне, вы также будете иметь доступ к обработчику событий, что позволит отслеживать прогресс выполнения задач и выводить результаты в контексте главного графического потока. Подробнее об этом классе в отдельной статье.

Хотя использование AsyncTask — хорошее решение, случается, что для работы в фоновом режиме приходится создавать собственные потоки и управлять ими.

В Java есть стандартный класс Thread, который вы можете использовать следующим образом:

Данный способ подходит только для операций, связанных с временем. Но вы не сможете обновлять графический интерфейс программы.

Если вам нужно обновлять интерфейс программы, то нужно использовать AsyncTask, о котором говорилось выше, или вы можете реализовать ваш собственный класс, наследованный от Thread, используя объект Handler из пакета android.os для синхронизации с потоком GUI перед обновлением пользовательского интерфейса.

Вы можете создавать дочерние потоки и управлять ими с помощью класса Handler, а также классов, доступных в пространстве имён java.lang.Thread. Ниже показан простой каркас для переноса операций в дочерний поток.

Плохое приложение

Напишем «плохое» приложение, неправильно использующее основной поток. Однажды мы писали программу для подсчёта ворон. На этот раз будем считать чёрных котов, которые перебегают нам дорогу. Зачем они это делают — молчит наука. Может быть собранная статистика поможет разгадать тайну. Добавим на экран активности кнопки и текстовую метку. Код для щелчка кнопки.

Для имитации тяжёлой работы программа делает паузу на двадцать секунд, а потом выводит текст с подсчётом котов. Если нажать на кнопку один раз и подождать двадцать секунд, то программа отработает как положено. Но представьте себе, что вы нажали на кнопку один раз. Программа запустила паузу. Вы, не дожидаясь окончания паузы, снова нажали на кнопку. Программа должна выполнить вашу команду, но предыдущая команда ещё не отработала и наступает конфликт. Попробуйте нажать на кнопку несколько раз с небольшими перерывами. В какой-то момент приложение зависнет и выведет системное диалоговое окно:

Читайте также:  Процесс com android settings что это

В реальных приложениях такое окно может разозлить пользователя и он поставит низкую оценку вашему приложению.

В данном случае ошибку вызывает не сам вывод текста в текстовой метке, который, к слову, тоже выполняется в основном потоке, а сам щелчок кнопки. Если вы закомментируете последние две строчки кода, связанные с TextView, то ошибка сохранится.

Вам необходимо перенести трудоёмкую задачу в отдельный поток. Для этого создаётся экземпляр класса Runnable, у которого есть метод run(). Далее создаётся объект Thread, в конструкторе у которого указывается созданный Runnable. После этого можно запускать новый поток с помощью метода start(). Перепишем пример.

Весь код мы перенесли в метод run(). Теперь вы можете безостановочно щёлкать по кнопке. На этот раз приложение сохранит свою работоспособность. Чтобы в этом убедиться, в код добавлено протоколирование логов Log.i(). При каждом нажатии создаётся новый поток, в котором выполняется код. Потоки друг другу не мешают и дожидаются своей очереди, когда система позволит им отработать.

Основной поток также называют UI-потоком. Имено в главном потоке можно обновить текст у текстовой метки. В создаваемых нами потоках это делать нельзя. Если вы уберёте комментарии с последнего примера и запустите проект, то получите сообщение об ошибке.

Нужен некий посредник между создаваемыми потоками и основным UI-потоком. В роли такого посредника служит класс Handler (полное название класса android.os.Handler, не перепутайте). Вам нужно создать экземпляр класса и указать код, который нужно выполнить.

После строчки кода с Log.i() добавьте вызов метода посредника.

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

Но бывает так, что от потока требуется получить информацию для обработки. Ниже упрощённый пример.

Запуск потока

Предположим, мы разрабатываем собственный проигрыватель. У нас есть кнопка Play, которая вызывает метод play() для воспроизведения музыки:

Теперь запустим метод в другом потоке. Сначала создаётся новый поток. Далее описывается объект Runnable в конструкторе потока. А внутри созданного потока вызываем наш метод play(). И, наконец, запускаем поток.

Усыпить поток

Иногда требуется временно приостановить поток («усыпить»):

Приоритет потоков

Для установки приоритета процесса используется метод setPriority(), который вызывается до запуска потока. Значение приоритета может варьироваться от Thread.MIN_PRIORITY (1) до Thread.MAX_PRIORITY (10):

Отмена выполнения потока

У потока есть метод stop(), но использовать его не рекомендуется, поскольку он оставляет приложение в неопределённом состоянии. Обычно используют такой подход:

Существует и другой способ, когда все запускаемые потоки объявляются демонами. В этом случае все запущенные потоки будут автоматически завершены при завершении основного потока приложения:

Источник

Android Studio — как остановить handler.postDelayed от фрагмента?

Описание:

Исследуя некоторое время, я пришел, чтобы найти следующую строку кода:

Я пробовал это, но это не могло решить мою проблему. Это ошибка, которую я получаю:

Я вызываю три обработчика, которые загружают элементы в три разных вида recycler и в разное время (это происходит потому, что если я загружаю их без ожидания, приложение вылетает из-за использования такого количества памяти или чего-то подобного).

Читайте также:  Как достать информацию с андроида с разбитым экраном

Проблема:

Пользователь «troll» может просто войти в мое приложение,а затем войти в этот фрагмент, в котором у меня есть мои 4 обработчика, и нажать кнопку назад, как только он войдет, и это тоже приведет к сбою моего приложения. Вот почему я хочу остановить обработчики (при нажатии кнопки Назад).

Что я могу сделать, чтобы исправить эту ошибку?

Что вам нужно знать:

Мой фрагмент с обработчиками находится внутри действия (конечно). Кнопка «Назад» находится в действии (а не во фрагменте).

Код «Fragment languages» JAVA:

Код активности (с кнопкой Назад) :

Edit (код класса отца java):

1 ответ

Я пытаюсь дать предупреждение при выходе из фрагмента разными способами, и пользователь может выбрать, чтобы остаться в текущем фрагменте. Разве это возможно? Как будто есть активность а и два фрагмента F1 & F2. Теперь вы находитесь в F2, задняя кнопка ведет к F1 и какой-то пункт меню В A.

Как я могу остановить android studio переход к библиотечным классам, которые я не заинтересован в отладке? Он продолжает заходить в библиотечные файлы, с которыми у меня нет проблем. Я хочу только шагнуть в исходный код своего проекта. Есть ли способ занести в черный список файлы, которые меня не.

Вы можете просто пропустить вызов метода, если фрагмент view уничтожен (фрагмент уничтожен или он находится в backstack). Есть способ getView()

Если вы используете методы hide/show FragmentTransaction , вы можете использовать метод isVisible() Fragment , потому что скрытые фрагменты view -это View.GONE (а не null )

Похожие вопросы:

Я не видел реального ответа на этот тип использования handler.posDelayed. Итак, я выполняю handler.posDelayed несколько раз с помощью for-loop. Проблема в том, что когда я покидаю действие и.

Как остановить запуск моего кода в Android Studio? Я попытался выбрать программу в папке Java,но кнопка Terminate Application неактивна. Это действительно раздражает, как долго сходит с ума, хотя я.

Должно быть, я упускаю что-то совершенно очевидное, но я не могу найти простой способ просто остановить запуск приложения. Я запускаю его на своем HTC One. Сначала я попытался переключить зеленую.

Я пытаюсь дать предупреждение при выходе из фрагмента разными способами, и пользователь может выбрать, чтобы остаться в текущем фрагменте. Разве это возможно? Как будто есть активность а и два.

Как я могу остановить android studio переход к библиотечным классам, которые я не заинтересован в отладке? Он продолжает заходить в библиотечные файлы, с которыми у меня нет проблем. Я хочу только.

Как я могу остановить Android Studio от обертывания строк методов и конструкторов? Вот как Android Studio в настоящее время это делает: Один класс public class Foo < public Foo(Context context.

Я использовал Eclipse раньше, и я мог бы легко остановить logcat от прокрутки, но я не могу найти ту же функциональность в Android studio. Кто-нибудь знает, как это сделать?

Кто-нибудь знает способ остановить профилировщика от. профилирования . в Android Studio 2.4+? Он использует тонну CPU главной машины, когда я на самом деле им не пользуюсь. Я знаю, что могу.

Я не могу остановить handler.postDelayed из приведенного ниже примера. Он просто продолжает выполнять функцию через 1 секунду и не останавливается, когда переключатель выключен.

После того, как я начал использовать отладку с подключением отладчика в Android Studio, я не могу установить автономный пакет — он говорит Waiting for debugger to attach ! Я не могу запустить.

Источник

Оцените статью