START_STICKY i START_NOT_STICKY

Odpowiedzi:

371

Oba kody są ważne tylko wtedy, gdy w telefonie zabraknie pamięci i zabije usługę przed zakończeniem działania. START_STICKYmówi systemowi operacyjnemu, aby odtworzył usługę po tym, jak będzie miała wystarczającą ilość pamięci, i zadzwoni onStartCommand()ponownie z pustą intencją. START_NOT_STICKYinformuje system operacyjny, aby nie zawracał sobie głowy ponownym odtwarzaniem usługi. Istnieje również trzeci kod, START_REDELIVER_INTENTktóry nakazuje systemowi operacyjnemu odtworzenie usługi i ponowne dostarczenie tego samego celu onStartCommand().

Artykuł Dianne Hackborn wyjaśnił tło tego znacznie lepiej niż oficjalna dokumentacja.

Źródło: http://android-developers.blogspot.com.au/2010/02/service-api-changes-starting-with.html

Kluczową częścią tutaj jest nowy kod wynikowy zwrócony przez funkcję, informujący system, co powinien zrobić z usługą, jeśli jej proces zostanie zabity podczas działania:

START_STICKY jest w zasadzie taki sam jak poprzednie zachowanie, w którym usługa jest pozostawiana „uruchomiona”, a później zostanie ponownie uruchomiona przez system. Jedyna różnica w porównaniu z poprzednimi wersjami platformy polega na tym, że jeśli zostanie ona zrestartowana, ponieważ proces zostanie zabity, funkcja onStartCommand () zostanie wywołana w następnej instancji usługi z zerową wartością Intent, zamiast w ogóle nie być wywoływana. Usługi korzystające z tego trybu powinny zawsze sprawdzać tę sprawę i odpowiednio sobie z nią radzić.

START_NOT_STICKY mówi, że po powrocie z onStartCreated (), jeśli proces zostanie zabity bez pozostałych poleceń startowych do dostarczenia, usługa zostanie zatrzymana zamiast ponownie uruchomiona. Ma to o wiele większy sens w przypadku usług, które mają być uruchamiane tylko podczas wykonywania wysyłanych do nich poleceń. Na przykład usługa może być uruchamiana co 15 minut od alarmu w celu sprawdzenia stanu sieci. Jeśli zostanie zabity podczas wykonywania tej pracy, najlepiej byłoby po prostu pozwolić, aby został zatrzymany i rozpocząć pracę przy następnym uruchomieniu alarmu.

START_REDELIVER_INTENT jest jak START_NOT_STICKY, z wyjątkiem sytuacji, gdy proces usługi zostanie zabity przed wywołaniem stopSelf () dla określonej intencji, ta intencja zostanie do niej ponownie dostarczona, dopóki się nie zakończy (chyba że po kilku kolejnych próbach nadal nie może zostać zakończona, w którym momencie system się poddaje). Jest to przydatne w przypadku usług, które odbierają polecenia pracy i chcą się upewnić, że ostatecznie wykonają pracę dla każdego wysłanego polecenia.

Frank Leigh
źródło
1
Jak uniknąć podwójnego wywoływania funkcji uchwyt handleStart (intent, startId); jak będą wywoływane zarówno onStart (), jak i onStartCommand? czy to dobry projekt? @Frank Leigh
Sazzad Hissain Khan
2
Jaka jest jednak domyślna flaga, jeśli nie określono żadnej?
IgorGanapolsky
3
Jeśli zastosujesz „return super.onStartCommand (...);” zobaczysz, że jeśli twoja docelowa wersja SDK jest mniejsza niż ECLAIR (API5 = 2.0) domyślnie zwracana jest START_STICKY_COMPATIBILITY, a od 2.0 i więcej START_STICKY jest zwracana.
MikeL
1
Co rozumiesz przez „bez pozostałych poleceń uruchamiania” w START_NOT_STICKY?
Malwinder Singh,
3
@FrankLeigh Nie zgadzam się, że START_REDELIVER_INTENTjest jak START_NOT_STICKY. Zamiast tego jest jakSTART_STICKY
CopsOnRoad
107

Odpowiedź KISS

Różnica:

START_STICKY

system spróbuje odtworzyć twoją usługę po jej zabiciu

START_NOT_STICKY

system nie będzie próbował odtworzyć usługi po jej zabiciu


Standardowy przykład:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return START_STICKY;
}
Oded Breiner
źródło
5
To właściwie nie jest poprawne i mylące. Błędem jest powiedzenie: „usługa została zabita”, ponieważ można pomyśleć, że odwołujesz się do stopSelf lub stopService, podczas gdy oczywiście masz na myśli proces zabity. Lepiej więc użyj tekstu w swojej odpowiedzi.
Ilya Gazman
Cześć, jak mogę przetestować START_REDELIVER_INTENT. Właśnie przetestowałem START_STICKYi zabiłem aplikację przez ostatnie aplikacje. Następnie przywołuje usługę. Ale START_REDELIVER_INTENTnigdy więcej nie zadzwoniłem. Czemu?
Asif Mushtaq
@IlyaGazman Z szacunkiem się nie zgadzam. Zatrzymane i zabite to dwa bardzo różne słowa. Ta odpowiedź wyjaśnia problem poprawnie w prosty i bezpośredni sposób.
NoHarmDan
23

Dokumentacja START_STICKYi START_NOT_STICKYjest dość prosta.

START_STICKY:

Jeśli proces tej usługi zostanie zabity podczas jej uruchamiania (po powrocie z onStartCommand(Intent, int, int)), pozostaw ją w stanie uruchomionym, ale nie zachowuj dostarczonego zamiaru. Później system spróbuje odtworzyć usługę. Ponieważ jest w stanie uruchomionym , gwarantuje wywołanie onStartCommand(Intent, int, int) po utworzeniu nowej instancji usługi; jeśli nie ma żadnych oczekujących poleceń uruchomienia, które zostaną dostarczone do usługi, zostanie ona wywołana z obiektem o zerowym zamiarze, więc należy to sprawdzić.

Ten tryb ma sens w przypadku rzeczy, które zostaną jawnie uruchomione i zatrzymane, aby działały przez dowolny czas, na przykład usługa wykonująca odtwarzanie muzyki w tle.

Przykład: próbka usługi lokalnej

START_NOT_STICKY:

Jeśli proces tej usługi zostanie zabity podczas jej uruchamiania (po powrocie z onStartCommand(Intent, int, int))i nie ma żadnych nowych zamiarów uruchomienia w celu jej dostarczenia, wyjmij usługę ze stanu uruchomionego i nie twórz jej ponownie, dopóki nie pojawi się wyraźne wywołanie w przyszłości Context.startService(Intent). nie otrzyma onStartCommand(Intent, int, int)połączenia z nullzamiarem, ponieważ nie zostanie ono ponownie uruchomione, jeśli nie będzie oczekujących na zrealizowanie zamiarów.

Ten tryb ma sens w przypadku rzeczy, które chcą wykonać jakąś pracę w wyniku uruchomienia, ale można je zatrzymać, gdy są pod presją pamięci i jawnie uruchomią się ponownie później, aby wykonać więcej pracy. Przykładem takiej usługi może być sondowanie danych z serwera: może zaplanować alarm, aby sondował co Nminutę, uruchamiając alarm. Gdy onStartCommand(Intent, int, int)zostanie wywołany z alarmu, planuje nowy alarm na N minut później i odradza wątek do nawiązania połączenia. Jeśli proces zostanie zabity podczas wykonywania tej kontroli, usługa nie zostanie uruchomiona ponownie, dopóki nie zostanie włączony alarm.

Przykład: ServiceStartArguments.java

Marvin Pinto
źródło
nie powodzenia chłopaki .. Nie byłem w stanie odnieść się do dokumentacji słowem laika. Chciałbym nawiązać do scenariusza w czasie rzeczywistym. Chciałbym pokazać przykład na urządzeniu. aby mogli łatwiej zrozumieć.
prago
dla START_STICKY i START_NOT_STICKY onStartCommand () zostanie wykonany tylko raz i wyjdzie z niego. Przeszedłem przez wskazaną przez ciebie próbkę, ale mam wątpliwości, ile razy onStartCommand () będzie wykonywany. jeśli ponownie zarejestruję START_STICKY i nadal spróbuję odtworzyć usługę, czy usługa wykona się na StartCommand?
prago
co stanie się z działaniem, gdy usługa zostanie ponownie utworzona? Czy aktywność jest również odtwarzana ponownie?
ransh
Chyba nigdy się nie dowiemy
Denny,