Background thread java android

How can I run code on a background thread on Android?

I want some code to run in the background continuously. I don’t want to do it in a service. Is there any other way possible? I have tried calling the Thread class in my Activity but my Activity remains in the background for sometime and then it stops. The Thread class also stops working.

class testThread implements Runnable < @Override public void run() < File file = new File( Environment.getExternalStorageDirectory(), "/BPCLTracker/gpsdata.txt" ); int i = 0; RandomAccessFile in = null; try < in = new RandomAccessFile( file, "rw" ); >catch (FileNotFoundException e) < // TODO Auto-generated catch block e.printStackTrace(); >catch (IOException e) < // TODO Auto-generated catch block e.printStackTrace(); >//String line =null; while ( true ) < HttpEntity entity = null; try < if ( isInternetOn() ) < while ( ( line = in.readLine() ) != null ) < HttpClient client = new DefaultHttpClient(); String url = "some url"; HttpPost request = new HttpPost( url ); StringEntity se = new StringEntity( line ); se.setContentEncoding( "UTF-8" ); se.setContentEncoding( new BasicHeader( HTTP.CONTENT_TYPE, "application/json" ) ); entity = se; request.setEntity( entity ); HttpResponse response = client.execute( request ); entity = response.getEntity(); i++; >if ( ( line = in.readLine() ) == null && entity != null ) < file.delete(); testThread t = new testThread(); Thread t1 = new Thread( t ); t1.start(); >> else < Thread.sleep( 60000 ); >// end of else > catch (NullPointerException e1) < e1.printStackTrace(); >catch (InterruptedException e2) < e2.printStackTrace(); >catch (IOException e1) < // TODO Auto-generated catch block e1.printStackTrace(); >>// end of while >// end of run > 

Hi. Can you please post some code as an example of what you have tried? There are different ways to run code on a background thread but you must remember if you are accessing any UI components you must access them on the UI thread by using the runOnUiThread() method.

Читайте также:  Php iconv koi8 r

9 Answers 9

  1. execute code on a background Thread
  2. execute code that DOES NOT touch/update the UI
  3. execute (short) code which will take at most a few seconds to complete

THEN use the following clean and efficient pattern which uses AsyncTask:

AsyncTask.execute(new Runnable() < @Override public void run() < //TODO your background code >>); 

Even though you want to update the UI you can use following code snippet inside run: activity.runOnUiThread(new Runnable() < @Override public void run() < //Update UI >>);

One thing to note is that AsyncTasks are qeued. If you use this for a bunch of server api calls, they will not run in parallel.

Remember Running Background, Running continuously is two different tasks.

For long-term background processes, Threads aren’t optimal with Android. However, here’s the code, and do it at your own risk.

To approach it in the right way, you need to Start Service First, Inside the service, you need to start the Thread/Async task Which needs Runnable.

Remember Service and Thread will run in the background but our task needs to make triggers (call again and again) to get updates, i.e. once the task is completed we need to recall the function for the next update.

Timer (periodic trigger), Alarm (Timebase trigger), Broadcast (Event base Trigger), recursion will awake our functions.

public static boolean isRecursionEnable = true; void runInBackground() < if (!isRecursionEnable) // Handle not to start multiple parallel threads return; // isRecursionEnable = false; when u want to stop // on exception on thread make it true again new Thread(new Runnable() < @Override public void run() < // DO your work here // get the data if (activity_is_not_in_background) < runOnUiThread(new Runnable() < @Override public void run() < // update UI runInBackground(); >>); > else < runInBackground(); >> >).start(); > 

Using Service: If you launch a Service it will start, It will execute the task, and it will terminate itself after the task execution if the service is not STICKY. This Service termination might also be caused by an exception in code or the user killed it manually from settings.

START_STICKY (Sticky Service) is the option given by Android that the service will restart itself if the service is terminated.

Remember the question difference between multiprocessing and multithreading? Service is a background process (Just like activity without UI), The same way how you launch thread in the activity to avoid load on the MainThread (Activity/UI thread), the same way you need to launch threads on service to avoid load on service.

In a single statement, if you want a run a background continues task, you need to launch a StickyService and run the thread in the service on event base

Источник

Потоки

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

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

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

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

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

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

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

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

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

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

 new Thread(new Runnable() < public void run() < //do time consuming operations >); > >).start(); 

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

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

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

 // Этот метод вызывается из главного потока GUI. private void mainProcessing() < // Здесь трудоемкие задачи переносятся в дочерний поток. Thread thread = new Thread(null, doBackgroundThreadProcessing, "Background"); thread.start(); >// Объект Runnable, который запускает метод для выполнения задач // в фоновом режиме. private Runnable doBackgroundThreadProcessing = new Runnable() < public void run() < backgroundThreadProcessing(); >>; // Метод, который выполняет какие-то действия в фоновом режиме. private void backgroundThreadProcessing()

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

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

 public void onClick(View view) < long endTime = System.currentTimeMillis() + 20 * 1000; while (System.currentTimeMillis() < endTime) < synchronized (this) < try < wait(endTime - System.currentTimeMillis()); >catch (Exception e) < >> > TextView infoTextView = (TextView) findViewById(R.id.textViewInfo); infoTextView.setText("Сегодня коты перебегали дорогу: " + mCounter++ + " раз"); > 

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

Thread

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

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

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

 public void onClick(View view) < Runnable runnable = new Runnable() < public void run() < // Переносим сюда старый код long endTime = System.currentTimeMillis() + 20 * 1000; while (System.currentTimeMillis() < endTime) < synchronized (this) < try < wait(endTime - System.currentTimeMillis()); >catch (Exception e) < >> > Log.i("Thread", "Сегодня коты перебегали дорогу: " + mCounter++ + " раз"); // Нельзя! // TextView infoTextView = // (TextView) findViewById(R.id.textViewInfo); // infoTextView.setText("Сегодня коты перебегали дорогу: " + mCounter++ + " раз"); > >; Thread thread = new Thread(runnable); thread.start(); > 

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

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

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

 Handler handler = new Handler() < @Override public void handleMessage(Message msg) < TextView infoTextView = (TextView) findViewById(R.id.textViewInfo); infoTextView.setText("Сегодня коты перебегали дорогу: " + mCounter++ + " раз"); >>; 

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

 Log.i("Thread", "Сегодня коты перебегали дорогу: " + mCounter++ + " раз"); handler.sendEmptyMessage(0); // Нельзя! // TextView infoTextView = // (TextView) findViewById(R.id.textViewInfo); // infoTextView.setText("Сегодня коты перебегали дорогу: " + mCounter++ + " раз"); 

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

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

 public void onClick(View view) < Runnable runnable = new Runnable() < public void run() < Message msg = handler.obtainMessage(); Bundle bundle = new Bundle(); SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss MM/dd/yyyy", Locale.US); String dateString = dateFormat.format(new Date()); bundle.putString("Key", dateString); msg.setData(bundle); handler.sendMessage(msg); >>; Thread thread = new Thread(runnable); thread.start(); > Handler handler = new Handler() < @Override public void handleMessage(Message msg) < Bundle bundle = msg.getData(); String date = bundle.getString("Key"); TextView infoTextView = (TextView) findViewById(R.id.textViewInfo); infoTextView.setText(date); >>; 

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

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

 Button playButton = (Button) findViewById(R.id.play); playButton.setOnClickListener(new View.OnClickListener()) < public void onClick(View v) < play(); // вызываем воспроизведение >> 

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

 Thread myThread = new Thread( // создаём новый поток new Runnable() < // описываем объект Runnable в конструкторе public void run() < play(); // вызываем метод воспроизведения >> ); 

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

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

 // засыпаем на 2 секунды (в миллисекундах) myThread.sleep(2000); 

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

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

 myThread.setPriority(10); myThread.start(); 

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

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

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

 myThread.setDaemon(true); myThread.start(); 

Источник

Android: How to work with background thread?

I’ve developed an application that takes content from the internet and shows it accordingly on the device’s screen . The program works just fine , a little bit slow . It takes about 3-4 seconds to load and display the content . I would like to put all the code that fetches the content and displays it in a background thread and while the program is doing those functions , I would like to display a progress dialog. Could you help me do this ? I would like especially to learn how to put the code in a background thread. MY CODE

public class Activity1 extends Activity < private ProgressDialog progressDialog; @Override public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.main); new AsyncTask() < ProgressDialog progressDialog; @Override protected void onPreExecute() < /* * This is executed on UI thread before doInBackground(). It is * the perfect place to show the progress dialog. */ progressDialog = ProgressDialog.show(Activity1.this, "", "Loading. "); >@Override protected Boolean doInBackground(Integer. params) < if (params == null) < return false; >try < /* * This is run on a background thread, so we can sleep here * or do whatever we want without blocking UI thread. A more * advanced use would download chunks of fixed size and call * publishProgress(); */ Thread.sleep(params[0]); // HERE I'VE PUT ALL THE FUNCTIONS THAT WORK FOR ME >catch (Exception e) < Log.e("tag", e.getMessage()); /* * The task failed */ return false; >/* * The task succeeded */ return true; > @Override protected void onPostExecute(Boolean result) < progressDialog.dismiss(); /* * Update here your view objects with content from download. It * is save to dismiss dialogs, update views, etc., since we are * working on UI thread. */ AlertDialog.Builder b = new AlertDialog.Builder(Activity1.this); b.setTitle(android.R.string.dialog_alert_title); if (result) < b.setMessage("Download succeeded"); >else < b.setMessage("Download failed"); >b.setPositiveButton(getString(android.R.string.ok), new DialogInterface.OnClickListener() < @Override public void onClick(DialogInterface dlg, int arg1) < dlg.dismiss(); >>); b.create().show(); > >.execute(2000); new Thread() < @Override public void run() < // dismiss the progressdialog progressDialog.dismiss(); >>.start(); > > 

Источник

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