2013-03-18 11 views
66

Desidero che alcuni codici vengano eseguiti in background continuamente. Non voglio farlo in un servizio. C'è un altro modo possibile?Come posso eseguire il codice su un thread in background su Android?

Ho provato a chiamare la classe Thread nel mio Activity ma il mio Activity rimane sullo sfondo per qualche tempo e poi si ferma. Anche la classe Thread smette di funzionare.

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


       }// end of if 
       else 
       { 
        Thread.sleep(60000); 

       } // end of else 
      }// end of try 
      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

Hi. Puoi per favore postare del codice come esempio di ciò che hai provato? Esistono diversi modi per eseguire il codice su un thread in background ma è necessario ricordare che se si accede a qualsiasi componente dell'interfaccia utente è necessario accedervi sul thread dell'interfaccia utente utilizzando il metodo 'runOnUiThread()'. –

+3

C'è qualche ragione particolare per non utilizzare il servizio – DeltaCap

+0

, ma non è consigliabile. il funzionamento continuo scaricherà la batteria del dispositivo. – HelmiB

risposta

17

Voglio un po 'di codice per l'esecuzione in background continuo. Non voglio farlo in un servizio. C'è un altro modo possibile?

Molto probabilmente mechanizm che stai cercando è AsyncTask. Progettato direttamente per l'esecuzione di processi in background su thread in background. Inoltre, il suo vantaggio principale è che offre alcuni metodi che funzionano sul thread Main (UI) e rendono possibile aggiornare l'interfaccia utente se si desidera informare l'utente di alcuni progressi nell'attività o aggiornare l'interfaccia utente con i dati recuperati dal processo in background.

Se non sai come iniziare qui è bel tutorial:

Nota: Inoltre v'è la possibilità di utilizzare IntentService con ResultReceiver che funziona pure.

+0

Grazie a Sajmon. Proverò questo – user2082987

+0

sory se sto facendo domande stupide – user2082987

+0

@ user2082987 così l'hai provato? – Sajmon

26

Per i processi in background a lungo termine, i thread non sono ottimali con Android. Tuttavia, ecco il codice e fallo a tuo rischio ...

Ricorda che il servizio o il thread verranno eseguiti in background ma il nostro compito deve fare il trigger (chiamare ancora e ancora) per ottenere gli aggiornamenti, cioè una volta che l'attività è completato abbiamo bisogno di richiamare la funzione per il prossimo aggiornamento.

Timer (trigger periodico), allarme (trigger a base di tempo), trasmissione (trigger base eventi), la ricorsione sveglierà le nostre funzioni.

public static boolean isRecursionEnable = false; 

void runInBackground() { 
    if (isRecursionEnable) 
     return; // Handle not to start multiple parallel threads 

    isRecursionEnable = true; // 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() { 
         //uddate UI 
         runInBackground(); 
        } 
       }); 
      } else { 
       runInBackground(); 
      } 
     } 
    }).start(); 
} 
+5

Non dimenticare di chiamare .start() sul nuovo thread (...) – dwbrito

+0

Si consiglia di utilizzare questo metodo per l'esecuzione di un SignalStrengthListener personalizzato in background per una media di 20 minuti, mentre si acquisiscono valori dal listener una volta al secondo aggiornare il thread dell'interfaccia utente? Qui c'è più contesto: http://stackoverflow.com/questions/36167719/asynctask-fatal-exception-when-calling-a-method-from-doinbackground?noredirect=1#comment59973788_36167719 – JParks

2

Un'alternativa a AsyncTask è robospice. https://github.com/octo-online/robospice.

Alcune delle funzionalità di robospice.

1.esecuisce le richieste di rete in modo asincrono (in un background AndroidService) (es: richieste REST utilizzando Spring Android) .notifica l'app, sul thread dell'interfaccia utente, quando il risultato è pronto.

2.è fortemente digitato! Esegui le tue richieste usando i POJO e ottieni POJO come risultati delle richieste.

3. non applicare alcun vincolo né sui POJO utilizzati per le richieste né sulle classi di attività utilizzate nei progetti.

4.cache risultati (in Json sia con Jackson e Gson, o Xml, o file di testo flat, o file binari, anche utilizzando ORM Lite).

5.notifies vostre attività (o di qualsiasi altro contesto) del risultato della richiesta di rete se e solo se sono ancora vivi

6.nessuna perdita di memoria, come Android Loader, a differenza di Android AsyncTasks notifica le attività sul loro thread UI.

7. utilizza un modello di gestione delle eccezioni semplice ma affidabile.

Campioni con cui iniziare. https://github.com/octo-online/RoboSpice-samples.

Un campione di robospice allo https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result.

+0

Come memorizzare un array ottenuto dalla rete a SQLite? Fondamentalmente mi piacerebbe: ottenere i dati dalla rete E salvarli sul mio SQLite - entrambi nel thread in background, quindi ottenere la mia interfaccia utente notificata per aggiornare ListView. Di solito lo faccio con IntentService, ma RoboSpice sta scrivendo meno. – Yar

+0

@yar è possibile utilizzare un servizio intent se si tratta di un'operazione di lunga durata. Inoltre puoi usare asynctask ma solo se è di breve durata. Puoi creare una discussione e fare tutte le tue cose lì. Non uso la robospizio da molto tempo ormai. Ci sono altre librerie di rete come il volley ... – Raghunandan

+0

OK grazie. Ho pensato di usare Robospice, ma sembra che non sia troppo bello (flessibile) per le mie esigenze. Uso IntentService per molto tempo con successo. – Yar

219

SE è necessario:

  1. eseguire codice su uno sfondo Discussione

  2. eseguire codice che NON toccare/aggiornare l'interfaccia utente

  3. execute (short) il codice che si terrà al massimo qualche secondo per completare

THEN utilizzare il seguente modello pulito ed efficiente che utilizza AsyncTask:

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

Nota: richiede il livello API 11 – friederbluemle

+0

Ho utilizzato il codice precedente che hai detto di inviare email che non ha collegamento con l'interfaccia utente. Per la prima volta, ha funzionato bene, ma se provo a eseguire di nuovo lo stesso codice, la mia app è rimasta bloccata. Devo uccidere AsyncTask dopo l'esecuzione del codice?. –

+1

perché non si usa il seguente che è più leggero: new Thread (nuovo Runnable() { @Override public void run() {// sfondo codice }} ) start(); – awardak

0
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; 
    } 
} 
+0

Benvenuti in StackOverflow. Le risposte con solo il codice in esse tendono a essere contrassegnate per la cancellazione in quanto sono "di bassa qualità". Si prega di leggere la sezione di aiuto sulla risposta alle domande, quindi prendere in considerazione l'aggiunta di alcuni commenti alla risposta. – Graham

Problemi correlati