Как запустить код в фоновом потоке на Android?

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

Я попытался вызвать класс Thread в своей Activity но моя Activity некоторое время остается в фоновом режиме, а затем останавливается. Класс Thread также перестает работать.

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

    }

Ответ 1

ЕСЛИ вам нужно:

  • выполнить код на фоновом потоке

  • выполнить код, который НЕ ДОЛЖЕН касаться/обновлять пользовательский интерфейс

  • выполнить (короткий) код, который займет не более нескольких секунд, чтобы завершить

THEN используйте следующий чистый и эффективный шаблон, который использует AsyncTask:

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

Ответ 2

Помните, что "Запуск фона", "Постоянный запуск" - это две разные задачи.

Для долгосрочных фоновых процессов потоки не являются оптимальными с Android. Тем не менее, здесь код и сделать это на свой страх и риск...

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

Таймер (периодический триггер), Тревога (триггер временной базы), Трансляция (триггер базы событий), рекурсия пробудит наши функции.

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();
}

Использование сервиса: если вы запустите сервис, он запустится, он выполнит задачу и сам прекратит работу. после выполнения задачи. прекращение также может быть вызвано исключением, или пользователь убил его вручную из настроек. START_STICKY (Sticky Service) - это опция, предоставляемая Android, при которой служба перезапускается сама, если служба прекращается.

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

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

Ответ 3

Я хочу, чтобы какой-то код работал в фоновом режиме непрерывно. Я не хочу сделать это в службе. Есть ли другой способ?

Скорее всего, механизм, который вы ищете, AsyncTask. Он непосредственно предназначен для выполнения фонового процесса в фоновом потоке. Кроме того, его основное преимущество заключается в том, что предлагает несколько методов, которые запускаются в потоке Main (UI) и позволяют обновлять ваш пользовательский интерфейс, если вы хотите сообщить пользователю о некотором прогрессе в задаче или обновить интерфейс с данными, полученными из фонового процесса.

Если вы не знаете, как начать здесь, это хороший учебник:

Примечание: Также есть возможность использовать IntentService с ResultReceiver, который также работает.

Ответ 4

Альтернативой AsyncTask является robospice. https://github.com/octo-online/robospice.

Некоторые из особенностей robospice.

1. выполняет асинхронные (в фоновом режиме AndroidService) сетевые запросы (например: запросы REST с использованием Spring Android).notify you app, в потоке пользовательского интерфейса, когда результат готов.

2. сильно набирается! Вы делаете свои запросы с помощью POJO, и вы получаете POJO в качестве результатов запроса.

3. Отсутствуют ограничения ни на POJO, которые использовались для запросов, ни на классах активности, которые вы используете в своих проектах.

4. показывает результаты (в Json как с Джексоном, так и с Gson, или Xml, или с плоскими текстовыми файлами, либо с двоичными файлами, даже используя ORM Lite).

5.notify ваши действия (или любой другой контекст) результата сетевого запроса, если и только если они все еще живы

6.no утечка памяти вообще, как Android-загрузчики, в отличие от Android AsyncTasks уведомляет о ваших действиях в их потоке пользовательского интерфейса.

7. использует простую, но надежную модель обработки исключений.

Образцы для начала. https://github.com/octo-online/RoboSpice-samples.

Образец robospice в https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result.

Ответ 5

class Background implements Runnable {
    private CountDownLatch latch = new CountDownLatch(1);
    private  Handler handler;

    Background() {
        Thread thread = new Thread(this);
        thread.start();
        try {
            latch.await();
        } catch (InterruptedException e) {
           /// e.printStackTrace();
        }
    }

    @Override
    public void run() {
        Looper.prepare();
        handler = new Handler();
        latch.countDown();
        Looper.loop();
    }

    public Handler getHandler() {
        return handler;
    }
}

Ответ 6

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

Слушатель:

public interface ESLThreadListener {

    public List onBackground();

    public void onPostExecute(List list);

}

Класс потока

public class ESLThread extends AsyncTask<Void, Void, List> {


    private ESLThreadListener mListener;

    public ESLThread() {

        if(mListener != null){

            mListener.onBackground();
        }
    }

    @Override
    protected List doInBackground(Void... params) {

        if(mListener != null){

            List list = mListener.onBackground();

            return list;
        }

        return null;
    }

    @Override
    protected void onPostExecute(List t) {
        if(mListener != null){

            if ( t != null) {
                mListener.onPostExecute(t);
            }
        }

    }


    public void setListener(ESLThreadListener mListener){

        this.mListener = mListener;
    }
}

Запустите разные коды:

  ESLThread thread = new ESLThread();
                        thread.setListener(new ESLThreadListener() {
                            @Override
                            public List onBackground() {
                                List<EntityShoppingListItems>  data = RoomDB.getDatabase(context).sliDAO().getSL(fId);

                                return data;

                            }

                            @Override
                            public void onPostExecute(List t) {

                                List<EntityShoppingListItems> data = (List<EntityShoppingListItems>)t;
                                adapter.setList(data);
                            }
                        });

                        thread.execute();