New thread this android

Потоки

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

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

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

Применение фоновых потоков — необходимое условие, если вы хотите избежать появления диалогового окна для принудительного закрытия приложения. Когда активность в 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. Ниже показан простой каркас для переноса операций в дочерний поток.

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

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

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

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

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

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

Читайте также:  Prology imap 7000 tab обновление андроида

Весь код мы перенесли в метод 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(), но использовать его не рекомендуется, поскольку он оставляет приложение в неопределённом состоянии. Обычно используют такой подход:

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

Источник

Потоки. Класс Thread и интерфейс Runnable

В русской терминологии за термином Thread укрепился перевод «Поток». Хотя это слово также можно перевести как «Нить». Иногда в зарубежных учебных материалах понятие потока объясняется именно на нитях. Продолжим логический ряд — там где нити, там и клубок. А где клубок, там и кот. Сразу видно, что у переводчиков не было котов. Так и возникла путаница. Тем более что существуют другие потоки под термином Stream. Переводчики, вообще странный народ.

Когда запускается любое приложение, то начинает выполняться поток, называемый главным потоком (main). От него порождаются дочерние потоки. Главный поток, как правило, является последним потоком, завершающим выполнение программы.

Несмотря на то, что главный поток создаётся автоматически, им можно управлять через объект класса Thread. Для этого нужно вызвать метод currentThread(), после чего можно управлять потоком.

Класс Thread содержит несколько методов для управления потоками.

  • getName() — получить имя потока
  • getPriority() — получить приоритет потока
  • isAlive() — определить, выполняется ли поток
  • join() — ожидать завершение потока
  • run() — запуск потока. В нём пишите свой код
  • sleep() — приостановить поток на заданное время
  • start() — запустить поток

Получим информацию о главном потоке и поменяем его имя.

Имя у главного потока по умолчанию main, которое мы заменили на CatThread.

Вызовем информацию о названии потока без указания метода.

В этом случае можно увидеть строчку Thread[main,5,main] — имя потока, его приоритет и имя его группы.

Создание собственного потока

Создать собственный поток не сложно. Достаточно наследоваться от класса Thread.

Объявим внутри нашего класса внутренний класс и вызовем его по щелчку, вызвав метод start().

Как вариант, перенести вызов метода start() в конструктор.

Создание потока с интерфейсом Runnable

Есть более сложный вариант создания потока. Для создания нового потока нужно реализовать интерфейс Runnable. Вы можете создать поток из любого объекта, реализующего интерфейс Runnable и объявить метод run().

Внутри метода run() вы размещаете код для нового потока. Этот поток завершится, когда метод вернёт управление.

Когда вы объявите новый класс с интерфейсом Runnable, вам нужно использовать конструктор:

В первом параметре указывается экземпляр класса, реализующего интерфейс. Он определяет, где начнётся выполнение потока. Во втором параметре передаётся имя потока.

После создания нового потока, его нужно запустить с помощью метода start(), который, по сути, выполняет вызов метода run().

Создадим новый поток внутри учебного проекта в виде вложенного класса и запустим его.

Читайте также:  Андроид звонок с камерой

Внутри конструктора MyRunnable() мы создаём новый объект класса Thread

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

Можно запускать несколько потоков, а не только второй поток в дополнение к первому. Это может привести к проблемам, когда два потока пытаюсь работать с одной переменной одновременно.

Ключевое слово syncronized — синхронизированные методы

Для решения проблемы с потоками, которые могут внести путаницу, используется синхронизация.

Метод может иметь модификатор syncronized. Когда поток находится внутри синхронизированного метода, все другие потоки, которые пытаются вызвать его в том же экземпляре, должны ожидать. Это позволяет исключить путаницу, когда несколько потоков пытаются вызвать метод.

Кроме того, ключевое слово syncronized можно использовать в качестве оператора. Вы можете заключить в блок syncronized вызовы методов какого-нибудь класса:

Looper

Поток имеет в своём составе сущности Looper, Handler, MessageQueue.

Каждый поток имеет один уникальный Looper и может иметь много Handler.

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

Поток получает свой Looper и MessageQueue через метод Looper.prepare() после запуска. Looper.prepare() идентифицирует вызывающий потк, создаёт Looper и MessageQueue и связывает поток с ними в хранилище ThreadLocal. Метод Looper.loop() следует вызывать для запуска Looper. Завершить его работу можно через метод looper.quit().

Используйте статический метод getMainLooper() для доступа к Looper главного потока:

Создадим два потока. Один запустим в основном потоке, а второй отдельно от основного. Нам будет достаточно двух кнопок и метки.

Обратите внимание, как запускаются потоки. Первый поток запускается с помощью метода start(), а второй — run(). Затем проверяем, в каком потоке мы находимся.

Эта тема достаточно сложная и для большинства не представляет интереса и необходимости изучать.

В Android потоки в чистом виде используются всё реже и реже, у системы есть собственные способы.

Источник

New thread this android

Android Threads Tutorial

Android starts a thread when a component in an app is requested to start. The thread created one per app is called the main thread. System creates a new thread when the requested component is the first one to start in the app. Subsequent requests to start any component within the same application will be run in the same thread.

If there are multiple tasks which the main thread can’t handle due to the number of request to it or due to long running tasks, you’ll have to create threads and run those tasks in it instead of on the main thread to improve your application responsiveness and prevent application not responding dialog.

Table of Contents

Running Code on Background Thread

You can add a piece of code, which you want to run on a worker thread, to a class which implements Runnable interface and its method run() and then start the worker thread by creating an instance of Thread, passing Runnable instance which has the code to be executed to its constructor and calling start on it.

The example shows how to download file on background thread. For downloading file it uses okhttp.

But the problem with running code on the worker thread is that you shouldn’t modify UI components from it because UI components are not thread safe. Updates to UI components should be done on the main thread. Android provides ways which can be used to update UI components from the worker threads.

Updating UI Components from Background Thread

Android provides Activity.runOnUiThread, View.post and View.postDelayed methods for updating UI components from background thread. In the code which runs on the background thread, whenever UI needs to be updated from background thread, you need to call runOnUiThread() method of activity by passing a new runnable which will be executed on the main thread.

Similarly, you can use post() or postDelaye() methods of View class to update UI from background thread. To do that, create runnable with the code that updates UI components and pass it to post() or postDelaye() methods and call this code on background thread when it needs to update UI components.

Читайте также:  С чего начать работать с андроидом

AsyncTask

Methods Activity.runOnUiThread, View.post and View.postDelayed can be used for simple tasks only because as the complexity of the code that needs to be run on main thread grows, it will be difficult to manage the code.

In complex scenarios, you can use AsyncTask to update UI components from worker thread. Please see AsyncTask example to learn how to use it.

Using AsyncTask can possibly lead to memory leaks if AsyncTask is defined as non static inner class and it holds a strong reference to activity context. That is because a non static inner class holds implicit reference to its enclosing class, due to that the activity can’t be garbage collected even after it finishes while AsyncTask is still running in the background.

To solve this problem, you need to define async task as static inner class and define weak reference to context.

Updating UI Using Handler and Looper

Another way to update Views with results from background thread is by using Handler. Handler needs to know the thread on which it needs to run. You can make Handler connect to a new Thread or an existing thread. To connect handler to an existing thread, you need to pass Looper object to it so that it will run on the same thread that Looper object runs on. To get main thread looper object, you need to call getMainLooper method on Looper class.

You need to implement Handler’s handleMessage method which is called by the system when it receives a message. System passes the message object received from the background thread to handleMessage method.

Message can be sent to handler from background thread using the handler object, back ground thread needs to have reference to the handler object in order for it to create a message and send it to system. To create a message object, you need to call obtainMessage() method on the handler passing results from background thread as data object that you want to send it to handler so that it can update UI on main thread. Finally, call sendToTarget() method on message object to send the message.

Running Background Tasks Using RxJava

Using RxJava, you can implement clean code to run tasks in background and update UI views on the main thread with results from the background process. Please see RxJava use cases and RxJava example for more information.

IntentService

So far we have seen creating a background thread, running a task on it and updating UI components on the main thread. This way of creating a background thread to run a task on it is useful to run a task on background thread once.

But if you want to run a task repeatedly with different set of data and one task at time meaning sequentially on background thread, then you can use IntentService. Please see IntentService tutorial for more information and example.

Thread Pool

To run multiple tasks at the same time, you can create thread pools using concurrency framework. You can use Executors and ThreadPoolExecutor classes to create thread pools.

The Executors class provides utility and factory methods for creating Executor, ExecutorService, and ScheduledExecutorService.

ThreadPoolExecutor executes tasks from the queue it holds when there is a free thread available in the thread pool. Task producer adds task to the task queue. ThreadPoolExecutor give more control over thread pool configuration.

You can create ExecutorService instance using Executors class and by calling newFixedThreadPool() method on it passing the number of threads that you want in the thread pool. Whenever you need to run a task on background thread, you just pass the task in the form of Runnable to ExecutorService object by calling execute() method on it.

About

Android app development tutorials and web app development tutorials with programming examples and code samples.

Источник

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