Chcę, aby jakiś kod działał w tle w sposób ciągły. Nie chcę tego robić w serwisie. Czy jest inny sposób?
Próbowałem zadzwonić do Thread
klasy w moim, Activity
ale Activity
przez jakiś czas pozostaje w tle, a potem to się zatrzymuje. Thread
Klasa przestaje również działać.
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
}
android
multithreading
user2082987
źródło
źródło
runOnUiThread()
metody.Odpowiedzi:
Jeśli potrzebujesz:
wykonać kod w tle Thread
wykonać kod, który NIE DOTYKA / aktualizuje interfejsu użytkownika
wykonuje (krótki) kod, który zajmie najwyżej kilka sekund
Następnie użyj następującego czystego i wydajnego wzorca, który używa AsyncTask:
AsyncTask.execute(new Runnable() { @Override public void run() { //TODO your background code } });
źródło
Pamiętaj: Running Background, Running Continuous to dwa różne zadania.
W przypadku długoterminowych procesów w tle wątki nie są optymalne w systemie Android. Jednak oto kod i zrób to na własne ryzyko ...
Pamiętaj, że Usługa lub Wątek będzie działać w tle, ale nasze zadanie musi wywołać wyzwalacz (dzwonić wielokrotnie), aby uzyskać aktualizacje, tj. Po zakończeniu zadania musimy przywołać funkcję do następnej aktualizacji.
Timer (wyzwalanie okresowe), alarm (wyzwalanie podstawy czasu), rozgłaszanie (wyzwalanie podstawy zdarzenia), rekurencja budzi nasze funkcje.
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(); }
Korzystanie z usługi: Jeśli uruchomisz usługę, uruchomi się, wykona zadanie i zakończy się. po wykonaniu zadania. przerwane może być również spowodowane przez wyjątek lub użytkownik zabił go ręcznie z ustawień. START_STICKY (Sticky Service) to opcja podana przez Androida, która uruchomi się ponownie, jeśli usługa zostanie zakończona.
Pamiętasz kwestię różnicy między przetwarzaniem wieloprocesowym a wielowątkowością? Usługa jest procesem w tle (podobnie jak działanie bez interfejsu użytkownika), w ten sam sposób, w jaki uruchamiasz wątek w działaniu, aby uniknąć obciążenia głównego wątku (wątek działania), w taki sam sposób, w jaki musisz uruchamiać wątki (lub zadania asynchroniczne) w usłudze aby uniknąć obciążenia usług.
W jednej instrukcji, jeśli chcesz uruchomić zadanie kontynuowania w tle, musisz uruchomić StickyService i uruchomić wątek w usłudze na bazie zdarzeń
źródło
Najprawdopodobniej mechanizm, którego szukasz, to
AsyncTask
. Jest bezpośrednio przeznaczony do wykonywania procesów w tle w wątku w tle. Jego główną zaletą jest również to, że oferuje kilka metod, które działają w wątku głównym (UI) i umożliwiają aktualizację interfejsu użytkownika, jeśli chcesz powiadomić użytkownika o pewnym postępie w zadaniu lub zaktualizować interfejs użytkownika za pomocą danych pobranych z procesu w tle.Jeśli nie wiesz, jak zacząć tutaj, to fajny tutorial:
Uwaga: istnieje również możliwość korzystania
IntentService
zResultReceiver
tego również.źródło
Prosty 3-liniowy
Prosty sposób na zrobienie tego, który znalazłem jako komentarz @awardak w odpowiedzi Brandona Rude :
new Thread( new Runnable() { @Override public void run() { // Run whatever background code you want here. } } ).start();
Nie jestem pewien, czy i jak to jest lepsze niż używanie,
AsyncTask.execute
ale wydaje się, że działa dla nas. Wszelkie uwagi dotyczące tej różnicy będą mile widziane.Dzięki, @awardak !
źródło
Alternatywą dla AsyncTask jest Robospice. https://github.com/octo-online/robospice .
Niektóre cechy Robospice.
1. wykonuje asynchronicznie (w tle AndroidService) żądania sieciowe (np. Żądania REST przy użyciu Spring Android). Powiadamiają aplikację w wątku UI, gdy wynik jest gotowy.
2. jest mocno wpisane! Wysyłasz swoje żądania za pomocą POJO i otrzymujesz POJO jako wyniki żądania.
3. nie wymuszaj żadnych ograniczeń ani na POJO używanych do żądań ani na klasach aktywności, których używasz w swoich projektach.
4. zapisuje wyniki w pamięci podręcznej (w Json z Jacksonami i Gsonem lub Xml lub zwykłymi plikami tekstowymi lub plikami binarnymi, nawet używając ORM Lite).
5. powiadamia twoje działania (lub w jakimkolwiek innym kontekście) o wyniku żądania sieciowego wtedy i tylko wtedy, gdy są one nadal żywe
6. nie ma żadnego wycieku pamięci, podobnie jak Android Loaders, w przeciwieństwie do Android AsyncTasks powiadamia o twoich działaniach w swoim wątku interfejsu użytkownika.
7. wykorzystuje prosty, ale solidny model obsługi wyjątków.
Na początek próbki. https://github.com/octo-online/RoboSpice-samples .
Próbka robospice pod adresem https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result .
źródło
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; } }
źródło
Jeśli potrzebujesz uruchomić wątek z różnymi kodami, oto przykład:
Słuchacz:
public interface ESLThreadListener { public List onBackground(); public void onPostExecute(List list); }
Klasa wątku
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; } }
Uruchom różne kody:
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();
źródło