Обработчик против AsyncTask vs Thread

Я немного запутался в различиях между Handlers, AsyncTask и Threads в Android. Я прочитал немало блогов и вопросов здесь, в Кару.

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

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

Однако Thread не может взаимодействовать с пользовательским интерфейсом, обеспечивает более "базовую" многопоточность, и вы упускаете все абстракции AsyncTask.

Тем не менее, я хотел бы, чтобы соединение с сокетом работало. Должно ли это быть выполнено в обработчике или потоке, или даже в AsyncTask? Взаимодействие с интерфейсом вообще не нужно. Имеет ли это значение с точки зрения производительности, которую я использую?

Между тем документация была значительно улучшена.

Ответ 1

Как говорится в Руководстве по фоновой обработке Android с помощью Handlers, AsyncTask и Loaders на сайте Vogella:

Класс Handler может использоваться для регистрации в потоке и обеспечивает простой канал для отправки данных в этот поток.

Класс AsyncTask инкапсулирует создание фонового процесса и синхронизацию с основным потоком. Он также поддерживает отчеты о ходе выполнения задач.

А Thread - это основной элемент многопоточности, который разработчик может использовать со следующим недостатком:

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

  • Синхронизация с основным потоком, если вы публикуете результаты обратно в пользовательский интерфейс
  • Нет по умолчанию для отмены потока
  • Нет пула потоков по умолчанию
  • Нет по умолчанию для обработки изменений конфигурации в Android

А что касается AsyncTask, как AsyncTask в " Справочнике разработчика Android":

AsyncTask позволяет правильно и легко использовать поток пользовательского интерфейса. Этот класс позволяет выполнять фоновые операции и публиковать результаты в потоке пользовательского интерфейса без необходимости манипулировать потоками и/или обработчиками.

AsyncTask разработан как вспомогательный класс для Thread и Handler и не представляет собой универсальную среду потоков. AsyncTasks в идеале следует использовать для коротких операций (максимум несколько секунд). Если вам нужно, чтобы потоки работали в течение длительных периодов времени, настоятельно рекомендуется использовать различные API, предоставляемые пакетом java.util.concurrent, такие как Executor, ThreadPoolExecutor и FutureTask.

Обновление май 2015: я нашел отличную серию лекций на эту тему.

Это поиск Google: лекция Дугласа Шмидта android параллелизм и синхронизация

Это видео первой лекции на YouTube

Все это является частью CS 282 (2013): Системное программирование для Android от Университета Вандербильта. Здесь плейлист YouTube

Дуглас Шмидт, кажется, отличный преподаватель

Важное замечание : Если вы находитесь в точке, где вы планируете использовать AsyncTask для решения проблем с AsyncTask, вам следует сначала проверить ReactiveX/RxAndroid на наличие более подходящего шаблона программирования. Очень хороший ресурс для получения обзора - изучение RxJava 2 для Android на примере.

Ответ 2

Если мы посмотрим на исходный код, то увидим, что AsyncTask и Handler написаны исключительно на Java. (Однако есть некоторые исключения. Но это не важный момент)

Так что в AsyncTask или Handler нет магии. Эти занятия делают нашу жизнь проще как разработчик.

Например: если программа A вызывает метод A(), метод A() может выполняться в другом потоке с программой A. Мы можем легко проверить это с помощью следующего кода:

Thread t = Thread.currentThread();    
int id = t.getId();

Почему мы должны использовать новый поток для некоторых задач? Вы можете Google для этого. Много много причин, например: тяжелый подъем, длительные работы.

Итак, чем же отличаются Thread, AsyncTask и Handler?

AsyncTask и Handler написаны на Java (внутренне они используют Thread), поэтому все, что мы можем сделать с помощью Handler или AsyncTask, мы также можем добиться с помощью Thread.

Чем действительно могут помочь Handler и AsyncTask?

Наиболее очевидной причиной является связь между потоком вызывающего и рабочим потоком. (Поток вызывающего: поток, который вызывает рабочий поток для выполнения некоторых задач. Поток вызывающего не обязательно должен быть потоком пользовательского интерфейса). Конечно, мы можем общаться между двумя потоками другими способами, но есть много недостатков (и опасностей) из-за безопасности потоков.

Вот почему мы должны использовать Handler и AsyncTask. Эти классы выполняют большую часть работы за нас, нам нужно только знать, какие методы переопределить.

Разница между Handler и AsyncTask заключается в следующем: используйте AsyncTask когда потоком вызывающего является поток пользовательского интерфейса. Вот что говорится в документе Android:

AsyncTask позволяет правильно и легко использовать поток пользовательского интерфейса. Этот класс позволяет выполнять фоновые операции и публиковать результаты в потоке пользовательского интерфейса без необходимости манипулировать потоками и/или обработчиками

Я хочу подчеркнуть два момента:

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

2) Нет необходимости манипулировать обработчиками. (означает: вы можете использовать Handler вместо AsyncTask, но AsyncTask - более простой вариант).

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

@: когда вы прочитаете документ Android, вы увидите:

Обработчик позволяет отправлять и обрабатывать объекты Message и Runnable, связанные с потоком MessageQueue

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

Сложно? Просто помните, что Handler может безопасно общаться с потоком вызывающего.

Ответ 3

После углубленного изучения, это прямо вперед.

AsyncTask:

Это простой способ использовать поток, не зная ничего о модели потока Java. AsyncTask предоставляет различные обратные вызовы, соответствующие рабочему потоку и основному потоку.

Используйте для небольших операций ожидания, например:

  • Получение некоторых данных из веб-служб и отображение над макетом.
  • Запрос базы данных.
  • Когда вы понимаете, что выполняемая операция никогда, никогда не будет вложенной.

Handler:

Когда мы устанавливаем приложение в android, оно создает поток для этого приложения с именем MAIN UI Thread. Все действия выполняются внутри этого потока. В соответствии с правилом модели однопоточного потока android мы не можем напрямую обращаться к элементам пользовательского интерфейса (bitmap, textview и т.д.) Непосредственно для другого потока, определенного внутри этого действия.

Обработчик позволяет вам общаться с потоком пользовательского интерфейса из другого фонового потока. Это полезно в android, поскольку андроид не позволяет другим потокам напрямую взаимодействовать с потоком пользовательского интерфейса. Обработчик может отправлять и обрабатывать объекты Message и Runnable, связанные с потоками MessageQueue. Каждый экземпляр Handler связан с одним потоком и очереди сообщений потоков. Когда создается новый обработчик, он привязан к очереди потоков/сообщений потока, который его создает.

Он лучше всего подходит для:

  • Он позволяет выполнять очередь сообщений.
  • Расписание сообщений.

Thread:

Теперь пришло время поговорить о потоке.

Thread - это родительский элемент как AsyncTask, так и Handler. Они как внутри, так и внутри, используют , вы также можете создать свою собственную модель потока, например AsyncTask и Handler, но для этого требуется хорошее знание Java Multi-Threading Implementation.

Ответ 4

An AsyncTask используется для выполнения некоторых фоновых вычислений и публикации результата в потоке пользовательского интерфейса (с дополнительными обновлениями обновлений). Поскольку вы не имеете отношения к пользовательскому интерфейсу, то более подходящим является Handler или Thread.

Вы можете создать фон Thread и передать сообщения обратно в основной поток с помощью метода Handler post.

Ответ 5

Нить

Android поддерживает стандартные потоки Java. Вы можете использовать стандартные потоки и инструменты из пакета " java.util.concurrent ", чтобы поместить действия в фоновый режим. Единственным ограничением является то, что вы не можете напрямую обновлять пользовательский интерфейс из фонового процесса.

Если вам нужно обновить пользовательский интерфейс из фоновой задачи, вам нужно использовать некоторые классы для Android. Вы можете использовать класс " android.os.Handler " для этого или класс " AsyncTask "

укротитель

Класс " Handler " может обновлять пользовательский интерфейс. Дескриптор предоставляет методы для получения сообщений и для запуска. Чтобы использовать обработчик, вы должны создать его подкласс и переопределить handleMessage() для обработки сообщений. Для обработки Runable вы можете использовать метод post(); Вам нужен только один экземпляр обработчика в вашей деятельности.

Вы можете отправлять сообщения через метод sendMessage(Message msg) или sendEmptyMessage.

AsyncTask

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

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

http://mobisys.in/blog/2012/01/android-threads-handlers-and-asynctask-tutorial/

http://www.slideshare.net/HoangNgoBuu/android-thread-handler-and-asynctask

Ответ 6

Thread:

Вы можете использовать новый Thread для длительных фоновых задач, не влияя на поток пользовательского интерфейса. В ветке Java вы не можете обновить ветку пользовательского интерфейса.

Так как обычный поток не очень полезен для архитектуры Android, были введены вспомогательные классы для потоков.

Вы можете найти ответы на свои вопросы на странице документации по производительности Threading.

Обработчик:

Handler позволяет отправлять и обрабатывать объекты Message и Runnable связанные с потоком MessageQueue. Каждый экземпляр Handler связан с одним потоком и этой очередью сообщений потока.

Существует два основных варианта использования Handler:

  1. Составить график сообщений и исполняемых файлов, которые будут выполнены как определенный момент в будущем;

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

AsyncTask:

AsyncTask позволяет правильно и легко использовать поток пользовательского интерфейса. Этот класс позволяет выполнять фоновые операции и публиковать результаты в потоке пользовательского интерфейса без необходимости манипулировать потоками и/или обработчиками.

Недостатки:

  1. По умолчанию приложение AsyncTask объекты AsyncTask оно создает, в один поток. Поэтому они выполняются последовательно и, как и в случае основного потока, особенно длинный рабочий пакет может блокировать очередь. По этой причине используйте AsyncTask для обработки рабочих элементов длительностью менее 5 мс.

  2. Объекты AsyncTask также являются наиболее распространенными нарушителями для неявных ссылок. Объекты AsyncTask представляют риски, связанные с явными ссылками.

HandlerThread:

Вам может понадобиться более традиционный подход к выполнению блока работы в более длинном потоке (в отличие от AsyncTask, который должен использоваться для рабочей нагрузки 5 мс), и некоторая возможность управлять этим рабочим процессом вручную. Поток-обработчик, по сути, является долго выполняющимся потоком, который захватывает работу из очереди и обрабатывает ее.

ThreadPoolExecutor:

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

Если рабочая нагрузка больше, а одного HandlerThread недостаточно, вы можете перейти к ThreadPoolExecutor

Однако я бы хотел, чтобы в сервисе работало сокетное соединение. Должно ли это выполняться в обработчике или потоке, или даже в AsyncTask? Взаимодействие с интерфейсом вообще не нужно. Имеет ли это значение с точки зрения производительности, которую я использую?

Поскольку взаимодействие с пользовательским интерфейсом не требуется, вы не можете использовать AsyncTask. Нормальные потоки не очень полезны и, следовательно, HandlerThread - лучший вариант. Поскольку вы должны поддерживать сокетное соединение, обработчик в главном потоке вообще бесполезен. Создайте HandlerThread и получите Handler из циклытеля HandlerThread.

 HandlerThread handlerThread = new HandlerThread("SocketOperation");
 handlerThread.start();
 Handler requestHandler = new Handler(handlerThread.getLooper());
 requestHandler.post(myRunnable); // where myRunnable is your Runnable object. 

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

final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            //txtView.setText((String) msg.obj);
            Toast.makeText(MainActivity.this,
                    "Foreground task is completed:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

в свой Runnable, вы можете добавить

responseHandler.sendMessage(msg);

Более подробную информацию о реализации можно найти здесь:

Android: тост в потоке

Ответ 7

По-моему, потоки не являются наиболее эффективным способом создания соединений сокетов, но они обеспечивают максимальную функциональность с точки зрения запуска потоков. Я говорю, что из-за опыта, работающие потоки в течение длительного времени заставляют устройства быть очень горячими и ресурсоемкими. Даже простой while(true) будет нагревать телефон за считанные минуты. Если вы говорите, что взаимодействие с пользовательским интерфейсом не важно, возможно, AsyncTask хорош, потому что они предназначены для долгосрочных процессов. Это только мое мнение.

UPDATE

Пожалуйста, не обращайте внимания на мой ответ выше! Я ответил на этот вопрос еще в 2011 году, когда я был гораздо менее опытным в Android, чем сейчас. Мой ответ выше вводит в заблуждение и считается неправильным. Я оставляю это там, потому что многие люди прокомментировали это ниже, исправляя меня, и я выучил свой урок.

В этой теме есть гораздо лучшие ответы, но я, по крайней мере, даю мне более правильный ответ. Нет ничего плохого в использовании обычного Java Thread; однако, вы действительно должны быть осторожны в том, как вы его реализуете, потому что неправильное выполнение может быть очень интенсивным с процессором (наиболее заметным симптомом может быть нагревание вашего устройства). AsyncTask довольно хороши для большинства задач, которые вы хотите запустить в фоновом режиме (общие примеры - дисковый ввод-вывод, сетевые вызовы и вызовы базы данных). Тем не менее, AsyncTask не следует использовать для особо длинных процессов, которые могут потребоваться для продолжения после закрытия пользователем приложения или перевода его устройства в режим ожидания. Я бы сказал, что в большинстве случаев все, что не входит в поток пользовательского интерфейса, можно позаботиться в AsyncTask.

Ответ 8

AsyncTask предназначен для выполнения не более нескольких секунд работы, выполняемой в фоновом режиме (не рекомендуется для мегабайт загрузки файлов с сервера или для вычисления интенсивной задачи процессора, такой как операции ввода-вывода файлов). Если вам нужно выполнить длительную операцию, вам настоятельно рекомендуется использовать собственные потоки java. Java предоставляет вам различные классы, связанные с потоками, чтобы делать то, что вам нужно. Используйте Handler для обновления потока пользовательского интерфейса.

Ответ 9

public class RequestHandler {

    public String sendPostRequest(String requestURL,
                                  HashMap<String, String> postDataParams) {

        URL url;

        StringBuilder sb = new StringBuilder();
        try {
            url = new URL(requestURL);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(15000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);


            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));
            writer.write(getPostDataString(postDataParams));

            writer.flush();
            writer.close();
            os.close();
            int responseCode = conn.getResponseCode();

            if (responseCode == HttpsURLConnection.HTTP_OK) {
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                sb = new StringBuilder();
                String response;
                while ((response = br.readLine()) != null){
                    sb.append(response);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (first)
                first = false;
            else
                result.append("&");

            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }

        return result.toString();
    }

}

Ответ 10

Позвольте мне попытаться ответить на этот вопрос здесь с помощью примера:) - MyImageSearch [Просьба ссылаться на изображение здесь основного экрана активности - содержащее текст редактирования текста/поиска/сетку)

MyImageSearch

Описание MyImageSearch. Когда пользователь вводит данные в текстовое поле редактирования и нажимает кнопку поиска, мы будем искать изображения в Интернете через веб-службы, предоставляемые flickr (вам нужно только зарегистрируйтесь там, чтобы получить ключ/секретный токен). Для поиска мы отправляем HTTP-запрос и GET JSON Data обратно в ответ, содержащий URL-адрес отдельных изображений, который мы будем использовать для загрузки вида сетки.

Моя реализация. В основном действии я определю внутренний класс, который расширяет AsyncTask, чтобы отправить HTTP-запрос в doInBackGround Method и получить JSON Response и обновить локальный ArrayList из FlickrItems, который я собирающийся использовать для обновления моего GridView с помощью FlickrAdapter (расширяет базовый адаптер) и вызывает адаптер .notifyDataSetChanged() в onPostExecute() AsyncTask, чтобы перезагрузить представление сетки. Обратите внимание, что здесь HTTP-запрос является блокирующим вызовом, из-за которого я сделал это через AsyncTask. И я могу кэшировать элементы в адаптере, чтобы увеличить производительность или сохранить их на SDCard. Сетка, которую я буду раздувать в FlickrAdapter, содержит в моей реализации индикатор прогресса и изображение. Ниже вы можете найти код для mainActivity, который я использовал.

Ответ на вопрос сейчас - Поэтому, как только мы получаем данные JSON для извлечения отдельных изображений, мы можем реализовать логику получения изображений в фоновом режиме с помощью Handlers или Threads или AsyncTask. Здесь следует отметить, что, поскольку мои загруженные изображения должны отображаться в главном потоке UI, мы не можем просто использовать потоки, поскольку они не имеют доступа к контексту. В FlickrAdapter выбор, который я мог бы подумать:

  • Выбор 1: Создайте LooperThread [extends thread] - и продолжайте загружая изображения последовательно в один поток, сохраняя этот поток open [looper.loop()]
  • Выбор 2: используйте пул потоков и отправьте runnable через myHandler, который содержит ссылку на мой ImageView, но поскольку представления в режиме Grid View рециркулируются, снова может возникнуть проблема, когда изображение с индексом 4 отображается в индексе 9 [загрузка может занять больше времени]
  • Выбор 3 [Я использовал это]: используйте пул потоков и отправьте сообщение myHandler, в котором содержатся данные, относящиеся к индексу ImageView и ImageView, поэтому при выполнении handleMessage() мы обновим ImageView, только если currentIndex соответствует индексу изображения, мы попытался загрузить.
  • Выбор 4: используйте AsyncTask для загрузки изображения в фоновом режиме, но здесь у меня не будет доступа к числу потоков, которые я хочу в пул потоков и он варьируется в зависимости от версии Android, но в Choice 3 я могу принять осознанное решение о размере пула потоков в зависимости от используемой конфигурации устройства.

Здесь исходный код:

public class MainActivity extends ActionBarActivity {

    GridView imageGridView;
    ArrayList<FlickrItem> items = new ArrayList<FlickrItem>();
    FlickrAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageGridView = (GridView) findViewById(R.id.gridView1);
        adapter = new FlickrAdapter(this, items);
        imageGridView.setAdapter(adapter);
    }

    // To avoid a memory leak on configuration change making it a inner class
    class FlickrDownloader extends AsyncTask<Void, Void, Void> {



        @Override
        protected Void doInBackground(Void... params) {
            FlickrGetter getter = new FlickrGetter();

            ArrayList<FlickrItem> newItems = getter.fetchItems();

            // clear the existing array
            items.clear();

            // add the new items to the array
            items.addAll(newItems);

            // is this correct ? - Wrong rebuilding the list view and should not be done in background
            //adapter.notifyDataSetChanged();

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            adapter.notifyDataSetChanged();
        }

    }

    public void search(View view) {
        // get the flickr data
        FlickrDownloader downloader = new FlickrDownloader();
        downloader.execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

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

Ответ 11

Зависит от того, какой из них выбрать, в зависимости от требования

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

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

AsyncTask используется для выполнения кода в течение нескольких секунд, который выполняется в фоновом потоке и передает его результат в основной поток ** * Ограничения AsyncTask 1. Асинхронная задача не привязана к жизненному циклу активности и продолжает выполняться, даже если ее активность уничтожена, тогда как загрузчик не имеет этого ограничения. 2. Все асинхронные задачи совместно используют один фоновый поток для выполнения, что также влияет на производительность приложения

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

Ответ 12

Handler - это среда связи между потоками. В android он в основном используется для связи с основным потоком путем создания и отправки сообщений через обработчик

AsyncTask - используется для выполнения приложений с большим сроком выполнения в фоновом потоке. При n AsyncTask вы можете выполнить операцию в фоновом потоке и получить результат в основном потоке приложения.

Thread - это легкий процесс для достижения concurrency и максимального использования процессора. В android вы можете использовать поток для выполнения действий, которые не касаются пользовательского интерфейса приложения.

Ответ 13

Нить

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

В Android все компоненты выполняются в одном основном потоке. Задачи очереди Android и выполняйте их одну за другой в главном потоке. Когда долго выполняющиеся задачи выполняются, приложение перестает отвечать на запросы.

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

укротитель

Поскольку android использует однопоточную модель, компоненты пользовательского интерфейса создаются не поточно-безопасными. Это означает, что доступ к ним должен иметь только созданный им поток, то есть компонент пользовательского интерфейса должен обновляться только в основном потоке. Поскольку компонент пользовательского интерфейса выполняется в основном потоке, задачи, выполняемые в рабочих потоках, не могут изменять компоненты пользовательского интерфейса. Это где Handler входит в картину. Обработчик с помощью Looper может подключаться к новому потоку или существующему потоку и запускать код, который он содержит в подключенном потоке.

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

AsyncTask

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

Пожалуйста, смотрите Android Thread, Handler, Asynctask и Пулы потоков для примеров.