Apps korrekt beenden - das warum und wie ..

  • Antworten:52
Gelöschter Account
  • Forum-Beiträge: 5.136

20.06.2009, 00:21:54 via Website

Da mir in der letzten Zeit immer öfter Apps begegnen, die nicht korrekt oder gar nicht beendet werden, möchte ich hier mal in Kürze vorstellen warum man das tun sollte und wie man es tun kann.

Kurz zur Geschichte:
In der heutigen Zeit begegnet einem als Programmierer immer öfter Software, die sich aufgrund der stark gesunkenen Speicherpreise in keinster Weise mehr um Dinge wie Heap, Memory und Rechenleistung kümmern. Standardargument der meisten Programmierer : Ist ja eh genug Mem vorhanden .. da brauch ich mich heutzutage nicht mehr drum kümmern.

Stimmt das so ?
Nun ja .. das ist so ein Ding mit dem Speicher ... Theoretisch hat der Entwickler schon recht.

ABER: Meistens vergessen die Entwickler dabei zwei wesentliche Dinge. Erstens bewegt man sich heutzutage meistens in multiuser/multitasking Umgebungen.
Das bedeutet : Ich teile meinen Applikationsspeicher mit anderen Applikationen und/oder Threads, ausserdem belaste ich den Garbage Collector der JVM (Java Virtuellen Maschine) .

Ein Segen von Java, nämlich die Objektorientierung, kann in kritischen Fällen hier zum echten Hund werden. Einerseits gepriesen und viel verwendet, kann andererseits die gefankenlose Verwendung von Objekten schnell zum echten Speicherfresser werden. So Objekte können nämlich bei schlechter Planung ganz schnell ganz groß werden, ohne das man das im Single-User Testfall zunächst bemerkt.

Aber ich will nun nicht zu weit ins theoretische abschweifen ... zurück zum Thema.

Was kann ich also tun:
Zunächst etwas sehr simples, die eigene Anwendung zur rechten Zeit korrekt beenden und somit der JVM
erlauben aufzuräumen. Konkret also dem Garbage Collector zu ermöglichen, benötigen Speicher von nicht mehr
benötigten Variablen, Objekten und so weiter freizuräumen.

Den korrekten Zeitpunkt, wann eine App. beendet werden kann sollte jeder Programmierer kennen. Grob dann, wenn
die App. alle Aufgaben erledigt hat und die Lifetime der Activity beendet ist.

Wie das korrekt geht:

Ganz einfach, an der oder den richtigen Stellen eines oder beides der folgenden Dinge tun:

1. Aufruf der Methode
1finish();

Die Methode ist aus dem Paket android.app.Activity und propagiert das Ende der Activity an mögliche Aufrufer. Bestenfalls also an
das Betriebssystem selbst. Jedenfalls werden hiernach die benutzten Ressourcen finalisiert und freigegeben.

Es gibt auch noch Methoden um andere Activitys zu beenden, bzw. diese Events abzufragen. Darum soll es hier aber nicht gehen.

2. Zusätzlich kann man noch
1System.exit(0);
aufrufen.
Diese Methode aus dem Paket java.lang.System beendet relativ hart die momentane JVM und gibt Ressourcen wieder frei.
Ruft man vorher noch runFinalizersOnExit(true); auf, werden vor dem beenden der App. sämtliche Objekte hart vom
Garbage Collector erfasst, dereferenziert und finalisiert. Das sollte allerdings nur in echten Härtefällen
erfolgen, da ein Garbage Collector Lauf ein sogenanntes Dead Second bewirkt. Die Dead Second bedeutet nichts anderes
als das während des Garbage Collector Laufs die gesamte JVM STEHT weil nichts anderes mehr geht und NUR GC betrieben
wird. Dieser Prozess hat in jeder JVM TOP Priorität und kann in Härtefällen schon mal mehrere Minuten dauern.
Also VORSICHT mit dieser Option, auch wenn sie sicher alles wegputzt.

Also Leute .. finish(); und System.exit(0); tun nicht weh, das geht sogar in EINER ZEILE ... ;)

Warum ist das auf Systemen wie dem Android so wichtig?

Garbage Collection bedeutet CPU Zeit, Cpu Zeit = AkkuLeistung und AKKU .. hamma wenig
Wenig Speicher bedeutet mehr Garbage Collection, mehr Garbage Collection mehr CPU ... usw.

Ihr seht, dass sich soetwas sehr schnell aufschaukeln kann. Also denkt auch an Euer Android
und den armen Akku. Aber vor allem an die User die sich ärgern warum das Ding wieder mal
so elendiglich langsam geworden ist. Es liegt (vielleicht) auch mit an Euch ;)

In diesem Sinne, happy coding.

Nächstes Mal beschreibe ich dann wie man völlig simple mal nen Quit Menü in seine Apps einbauen
kann. Bis dahin ..

lg
voss

lg Voss

Petro HayeAnton S.Gelöschter Account

Antworten
Kevin T.
  • Forum-Beiträge: 337

20.06.2009, 02:23:24 via Website

Sehr kuhl Herr Voss ;)
Sollte auch unterstützt werden, denn es nervt nix mehr als ein Proggi das noch lebt obwohl man es schon lange nicht mehr benutzt ...

Antworten
Gelöschter Account
  • Forum-Beiträge: 5.136

20.06.2009, 09:30:48 via Website

Danke Kevin,

aber sagt doch einfach Jörg .. :grin:

lg
Voss

lg Voss

Antworten
Kevin T.
  • Forum-Beiträge: 337

21.06.2009, 17:06:51 via Website

Schon klar ;)

ich varriere nur gerne in meinen anreden ... :D

Antworten
Gelöschter Account
  • Forum-Beiträge: 5.136

21.06.2009, 17:58:59 via Website

Ok Sir Kevin :bashful:

Um zum Thema zurückzukommen

1finish();
2System.exit(OFF_TOPIC);


lg
Voss

— geändert am 21.06.2009, 17:59:45

lg Voss

Antworten
Mac Systems
  • Forum-Beiträge: 1.727

22.06.2009, 11:22:39 via Website

Ist das seitens der Docu mit dem System.exit(id) irgendwo nachzulesen (Link bitte) ?

Habe meinerseits nirgends so was gelesen, stattdessen wird gesagt das in der Start Activity die finish Methode aufgerufen werden soll.

Wieso Ich das System.exit anzweifele ist daher begründet das die VM eine eigene Sandbox hat aber alle Apps doch in der gleichen VM laufen, daher würde ich erwarten das ein System.exit eine nicht implementiere Methode ist. Seit Java 5 ist das Class-Sharing allgemein verfügbar und Android nutzt das ja irgendwie auch, allerdings ist es in Java 5 so das wenn zwei Applikationen gleichzeitig in der JVM laufen und eine davon System.exit aufruft die andere plötzlich beendet, was zu Datenverlust führen kann.

Ich würde daher in meinen APPs von Activity eine Abstrakte Klasse ableiten und diese weiß welche die Start Activity ist. Rufe Ich nun finish auf einer dieser Klassen auf sollte das sauber sein.

- mac

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten
Gelöschter Account
  • Forum-Beiträge: 5.136

22.06.2009, 13:24:19 via Website

Auf dem G1 läuft die sogn. Dalvik VM die gemeinsam mit dem darunterliegenden Linux-Kernel
so ausgelegt wurde, dass jede Applikation in einer eigenen VM-Instanz, bzw. einem eigenständigen
Linux Prozess läuft.
Diese VM, der Applikation wird mit einem system.exit(0) beendet, nichts anderes. Dabei werden
natürlich auch alle, wirklich alle Threads die mit dieser Applikation verknüpft sind, hart beendet.

Sollte eine Applikation derartige asynchrone Threads laufen haben muss man sich natürlich darum
kümmern diese vorher sauber zu beenden. Das finish() beendet lediglich die aktuelle Activity und die
mit ihr verbundenen laufenden Aktivitäten. Nicht unbedingt Threads die noch laufen und dann vielleicht
später noch nicht freigegebene Referenzen auf dem Stack hinterlassen.

Jedenfalls werden keinerlei andere VMs von dem in Deiner VM aufgerufenen system.exit() beeinflusst.

System.exit ist aus der java.lang.system und das ist dokumentiert, unter anderem, in der Android Developer
referenz unter: http://d.android.com/reference/java/lang/System.html#exit(int)

system.exit(0) geht absolut sicher, dass wirklich alles aufgeräumt wird durch den GC.
Das ist bei einem finish() nicht immer so unbedingt gesichert. Je nach Code implementierung eben.

voss

lg Voss

Antworten
Mac Systems
  • Forum-Beiträge: 1.727

22.06.2009, 13:42:11 via Website

Hmm, das werde Ich mir nachher mal ansehen. Wie sieht es denn aus wenn Ich eine Activity mittels finish() beende und meine Threads mittels #setDaemon(true) markiere ?

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten
Gelöschter Account
  • Forum-Beiträge: 5.136

22.06.2009, 14:05:08 via Website

Keine Ahnung,

ich würde aber vermuten, dass die mit system.exit() ebenfalls gekillt werden.

voss

lg Voss

Antworten
Mac Systems
  • Forum-Beiträge: 1.727

22.06.2009, 17:40:36 via Website

Klar werden diese "gekillt" doch sind Daemon Threads in verbindung mit UI Toolkits gang und gäbe. Unter Swing / AWT z.b wird die JVM diese Threads einfach beenden sobald das UI "stirbt" bzw die Main methode letztendlich verlassen wird.

— geändert am 22.06.2009, 17:47:44

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten
Gelöschter Account
  • Forum-Beiträge: 87

22.06.2009, 20:23:40 via Website

Ich fand deinen Bericht sehr interessant wenn ich auch in einigen Punkten nicht so ganz zustimme.

Es ist wie du sagst sehr wichtig bei Systemen mit begrenztem Speicher und parallel laufenden Applikationen so effizient und speichersparend zu programmieren wie es nur geht.

Prinzipell jede Applikation mit finish() zu beenden halte ich jedoch in einigen Fällen für ziemlich kontraproduktiv. Insbesondere wenn die Applikation als Teil eines Tasks verwendet werden könnte.

Das schöne an Android ist ja genau das Task Konzept, wonach mittels Intents Funktionen von anderen Applikationen verwendet werden können die oft für den User nicht den Anschein haben als würde es eine andere Applikation sein. Wenn du nun deine Applikation mit finish() beendest und sie Teil eines Tasks war, machst du damit den gesamten Task des Users zunichte, weil er nicht mehr wie gewohnt mit seiner "Back" Taste zum vorherigem Screen wechseln kann.

Im Allgemeinen stört man damit das Konzept welches hinter Android steht. Solltest du eine volkommene Standalone App entwickeln die nie und nimmer an einem Task teilnimmt ist das vielleicht nicht ganz so schlimm, aber es kann trotzdem für den User unbefriedigend sein wenn er nicht wie gewohnt die "Back" Taste nutzen kann.

Nur mal so nachgedacht.

Antworten
Mac Systems
  • Forum-Beiträge: 1.727

22.06.2009, 20:46:25 via Website

@Abraxas Son: Was ist für dich ein Task ? Ein Thread ? Oder eine Activity die mittels Intent aufgerufen wurde ?

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten
Gelöschter Account
  • Forum-Beiträge: 87

23.06.2009, 19:34:47 via Website

Mac Systems
@Abraxas Son: Was ist für dich ein Task ? Ein Thread ? Oder eine Activity die mittels Intent aufgerufen wurde ?


Ein Task ist ein Arbeitsgang in welchem mehrere Activities (auch über Applikationsgrenzen hinweg) involviert sind.

Aber wirklich genau definiert ist es unter folgendem Link:

Activity and Task Design

Antworten
Gelöschter Account
  • Forum-Beiträge: 5.136

24.06.2009, 09:30:59 via Website

Hallo Abraxas,

natürlich nicht jede Applikation da gebe ich Dir völlig Recht
... theoretisch zumindest aber dazu gleich mehr.

Der Entwickler einer Applikation muss ja den Lebenszyklus seiner Anwendung genau
kennen. Nicht jede Anwendung arbeitet nun mit Threads und Hintergrundausführung.
Bspw. hab ich eine kleine App. geschrieben die nix anderes tut, als Wlan ein oder
auszuschalten. Die braucht theoretisch nicht mal ne View, weil sie über einen view-unabhängigen
Toast nur eine kurze Bestätigung dessen ausgibt was sie nun gemacht hat.
Die wird sofort nach Ausführung wieder korrekt beendet und dümpelt nicht länger
im Speicher herum.

Schreibe ich nun aber eine Applikation die auf SystemBroadcasts reagiert oder eine Api
für andere Applikationen bereitstellt, dann muss ich mir ggf. sehr wohl Gedanken darum
machen ob überhaupt und wann ich eine Applikation wie beende. Gebe ich dem Benutzer die Möglichkeit
über einen Quit Button, mache ich das von einem Systemzustand abhängig, oder gar von der
Anwesenheit anderer Applikationen im Prozesskontext, oder oder oder.

Ich wurde bis jetzt mangels entsprechender Herausforderung noch nicht direkt mit dem
LifeCycle Konzept von Android konfrontiert, werde aber jetzt wohl daran gehen müssen
dieses näher zu ergründen weil ich so einen Background task benötigen werde.
Ich werd dann mal berichten was ich mir da so zu ausgedacht habe.

Das mit der Backtaste .. ist sicherlich auch Teil des gesamten Android LifCycle
Managements. Hier kommen die Funktionen onDestroy onPause onRestart und wie sie
heissen ins Spiel. Diese sollten in einem vernünftigen APplikationsdesign sicherlich
eingang finden und sind wichtig für die User-Experience beim Erleben der Anwendung.
Im Android kann eine Applikation ja auch jederzeit vom System beendet werden, wenn
der Speicherplatz ausgeht. Um so wichtiger ist das also.

Beende ich meinen Applikationstask, und kümmere mich um korrekte Rückgabewerte,
dann beende ich wirklich nur meinen eigenen Kontext. Das andere muss die aufrufende
App. erledigen. Hier muss der onResume Zweig korrekt implementiert sein.

Beende ich eine Applikation mit finish() wird ja das Activity Result vom System
automatisch an ggf. meine Activity aufrufende Intents an den onActivityResult Handler
zurückpropagiert. Hierfür gibt es auch die Methode setResult() die eben diese Parameter
setzt.

Alles in allem denke ich und weiss aus Beruflicher Erfahrung, dass Applikationsdesign
kein einfaches Geschäft ist und sich hinter einer vermeintlich einfachen Anwendung
viele Detailfragen verbergen, die zunächst oft ausser Acht gelassen werden und erst
viel zu spät im Entwicklungsprozess aufpoppen. Dann ist es jedoch oft aus Kostengründen
kaum noch möglich, dass App. Design noch auf die richtige Schiene zu bringen und man
beginnt sich mit Workarounds zu behelfen, die einem das Leben richtig schwer machen
und der Experience der Applikation nicht wirklich förderlich sind.

Ich hab ja auch geschrieben, dass dieser öffnende Thread erst der Anfang wäre. Ich denke
dass wir gerade mit kritischen Anmerkungen wie jetzt von Dir, oder wie von MacSystems
alle gemeinsam die Möglichkeit haben viel voneinander zu lernen und unserer Erfahrungen
und bereits erlebten Fussfallen auszutauschen.

Ich für meinen Teil finde es jedenfalls ungemein hilfreich mit Euch über diese Dinge
diskutieren zu können und sich auszutauschen.

lg
Voss

lg Voss

Antworten
Mac Systems
  • Forum-Beiträge: 1.727

24.06.2009, 10:18:50 via Website

Hoffen wir das beste, bis jetzt sieht der Lifecyle überschaubar aus. Zumindest muss Ich nichts eigenes erfinden.
Heute steht mein erster Service für meine kleine Applikation an, nachdem Ich gestern das Parcelable verstanden habe kann es weiter gehen.

— geändert am 24.06.2009, 10:23:11

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten
Gelöschter Account
  • Forum-Beiträge: 87

24.06.2009, 22:24:15 via Website

Ich hab ja auch geschrieben, dass dieser öffnende Thread erst der Anfang wäre. Ich denke
dass wir gerade mit kritischen Anmerkungen wie jetzt von Dir, oder wie von MacSystems
alle gemeinsam die Möglichkeit haben viel voneinander zu lernen und unserer Erfahrungen
und bereits erlebten Fussfallen auszutauschen.


genauer deiner Meinung Jörg!

Antworten
Gelöschter Account
  • Forum-Beiträge: 5.136

24.06.2009, 22:56:12 via Website

:grin: *Handschüttel*

lg Voss

Antworten
Markus Gu
  • Forum-Beiträge: 2.644

26.06.2009, 12:21:18 via Website

hab nochmal ein wenig drüber nachgedacht.

bei den von google bereitgestellten offizellen apps, gibts nirgends eine möglichkeit die app zu beenden. die werdens ja am besten wissen

swordiApps Blog - Website

Antworten
Anton S.
  • Forum-Beiträge: 1.614

27.06.2009, 20:40:08 via Website

Markus Gursch
hab nochmal ein wenig drüber nachgedacht.

bei den von google bereitgestellten offizellen apps, gibts nirgends eine möglichkeit die app zu beenden. die werdens ja am besten wissen

Ob das aber richtig ist, ist wieder eine andere Frage.

Am liebsten wäre mir ja eine Art Taskleiste, die immer im Sichtfeld ist und mir zeigt, welche Apps gerade noch im Background laufen. Ein Widget auf dem Homescreen für den Task Manager Lite wäre ideal, finde ich.

Neu bei Android, AndroidPIT oder dem App Center? Hier erfährst Du alles Wichtige: http://bit.ly/ccFQvI

Antworten
Markus Gu
  • Forum-Beiträge: 2.644

27.06.2009, 23:43:20 via Website

hehe naja überleg mal

das betriebssystem kommt hauptsächlich von google ( auch wenn da andere dabei sind. google ist da sicher die stärkste macht )

die programme kommen von google

also ich würd sagen eher machen die es richtig, als irgendein lustiger kleiner programmierer vom berg

swordiApps Blog - Website

Antworten
Gelöschter Account
  • Forum-Beiträge: 87

28.06.2009, 00:11:26 via Website

Die Idee von Android ist ja, dass der Lifecylce nicht vom Anwender, sondern vom Betriebssystem geregelt wird. Daher machen das die meisten apps auch nicht., da es wie schon gesagt die Experience stört wenn jede App sich selbst beenden würde.

Antworten
Anton S.
  • Forum-Beiträge: 1.614

28.06.2009, 17:54:08 via Website

Markus Gursch
hehe naja überleg mal

das betriebssystem kommt hauptsächlich von google ( auch wenn da andere dabei sind. google ist da sicher die stärkste macht )

die programme kommen von google

also ich würd sagen eher machen die es richtig, als irgendein lustiger kleiner programmierer vom berg

Und wenn du noch deinen Gedanken weiterführst, wirst du feststellen, dass Google genauso begonnen hat zu existieren. Es waren damals auch nur 2 kleine Entwickler vom Berg. Deine Behauptung an sich, dass ein großes Unternehmen mehr Know-How hat als ein einziger Entwickler, finde ich ein wenig oberflächlich.

Zum Glück hat jeder seine eigene Meinung ;-)

Neu bei Android, AndroidPIT oder dem App Center? Hier erfährst Du alles Wichtige: http://bit.ly/ccFQvI

Antworten
Markus Gu
  • Forum-Beiträge: 2.644

28.06.2009, 22:17:29 via Website

nana

musst schon genau lesen.

ich hab net gesagt, dass eine große firma mehr know how hat als eine kleine

ich hab gesagt, dass google, als entwickler des betriebssystems, eher weiß, wie man dafür optimal entwickelt, als irgendwer anderes

na mal ganz ehrlich, wenn google net weiß, wie man richtig für ihr eigenes betriebssystem programmiert, dann sollten sie ganz schnell die branche wechseln

swordiApps Blog - Website

Antworten
Gelöschter Account
  • Forum-Beiträge: 5.136

28.06.2009, 23:51:19 via Website

Die tun sich aber auch leichter es "anders" zu machen Markus.

Da gibt es genügend Beispiele.

Der HomeButton ist als einziger HardwareButton offiziell nicht abzufangen,
an gewisse Phone Funktionen, wie bspw. das Auflegen kommt man nicht heran,

Wie ich in den letzten Tagen feststellen konnte, werden sehr wohl einige Applikationen von Google
korrekt beendet, ohne dabei jedoch einen offiziellen Quit Button anzubieten.

Die Applikationen wie bspw. Google Maps dümpeln nach dem drücken auf den Homebutton noch kurz als IDLE auf der Applications-Liste umeinander nachdem sie vorher ForeGround oder BackGround Status hatten.

Das passiert in dieser Geschwindigkeit nur dann wenn der GarbageCollector (der zu dieser Zeit keine Speicher freischaufeln muss weil genügend da ist) die Objekte finalisieren kann.

Das bedeutet aber, dass automatisch bei bestimmten Stati der App. an bestimmten Stellen oder Laufzeitpunkten einfach ein finish eingebaut wurde.

Ich für meinen Teil finde es allerdings eher ungut, weil damit die Kontrolle über diese Dinge dem Anwender entzogen wird. Wehtun würde es bei den meisten Apps jedenfalls nicht.

Alles nur dem GC zu überlassen der "IRGENDWANN" aufräumt .. (selbst wenn man Ihn explizit aufruft) ist keine best Practice .. gerade wenn man bedenkt das darunter unter Umständen andere Applikationen und auch die Akkulebenszeit leiden muss.

Jeder der sich mal längere Zeit mit Profiling von Applikationen in Multiuser/Multitaskingumgebungen befasst hat, wird das bestätigen können.

Das mit dem "besser oder richtig machen" sehe ich in sofern nicht unbedingt als ein valides Argument an.
Die Googelianer haben einfach andere Möglichkeiten, oder sagen wir einfachere Möglichkeiten an gewisse Dinge heranzukommen. Wenn ein Programmierer oder ein Team etwas macht, muss es nicht heißen das man es nicht anders auch machen könnte. Vielleicht sogar besser ;)

Vielleicht hab ich letzteres aber auch schon einfach zu oft erlebt ..

lg
Voss

lg Voss

Antworten
Anton S.
  • Forum-Beiträge: 1.614

29.06.2009, 09:59:01 via Website

Markus Gursch
nana

musst schon genau lesen.

ich hab net gesagt, dass eine große firma mehr know how hat als eine kleine

ich hab gesagt, dass google, als entwickler des betriebssystems, eher weiß, wie man dafür optimal entwickelt, als irgendwer anderes

na mal ganz ehrlich, wenn google net weiß, wie man richtig für ihr eigenes betriebssystem programmiert, dann sollten sie ganz schnell die branche wechseln

Aus dem Wortlaut heraus, hört es sich aber so an ;-)

Google wußte bis vor kurzem anscheinend auch noch nicht, dass es ein Feld für Geburtstage bei den Kontakten vorhanden sein sollte. Von daher ist deine Aussage auch nicht ganz richtig.

Es kann sich ja jeder sein eigenes Bild davon machen.

Neu bei Android, AndroidPIT oder dem App Center? Hier erfährst Du alles Wichtige: http://bit.ly/ccFQvI

Antworten
Mirko Herbig
  • Forum-Beiträge: 48

02.07.2009, 21:44:48 via Website

Auch wenn der Thread schon einpaar Tage alt ist, will ich doch mal meine Gedanken zu dieser Diskussion schreiben.

Der Ansatz von Android den Activity* Lifecycle dem Betriebssystem zu überlassen ist schon etwas gewöhnungsbedürftig, sowohl für den Nutzer als auch für den Programmierer. Am Anfang war ich immer leicht irritiert, weil ich die Anwendungen schließen wollte, um Batterie und Arbeitsspeicher zu sparen. Nach einer weile Benutzung von Android und der Beschäftigung mit dem Livecycle finde ich es recht clever, wie Android das gelöst hat. Die Philosophie dahinter ist, dass das Laden und Beenden einer App mehr CPU (Strom + Zeit) kostet, als wenn die zuletzt benutzten Anwendungen einfach im Speicher bleiben. Wird der Speicher knapp, werden die Apps mit der niedrigsten Prio zuerst beendet. Welche Prio einer App zugeordnet ist, ist abhängig von deren Lifecycle Status. Das Besondere daran ist, dass nur die sichtbare Activity und deren Threads wirklich aktiv sind, alle nicht sichtbaren sind mindestens im Status onPause und verbrauchen keine CPU, das gilt auch für alle Backround-Threads dieser Activities, diese laufen nicht einfach weiter. Einzig Services bleiben aktiv (CPU), auch wenn die dazugehörige Activity nicht sichtbar ist.

Das Ganze soll jetzt für die Programmierer kein Freibrief sein, um verschwenderisch mit dem Speicher umzugehen, da gebe ich Jörg schon recht. Allerdings bin ich der Meinung, dass das aktive Beenden einer Anwendung durch den Nutzer oder Programmierer im Android-Framework eher das Gegenteil bewirkt. Ich gebe Speicher frei den ich nicht sofort wieder brauche, dafür aktiviere ich den Grabe Collector, welcher CPU verbraucht. Ich irritiere evtl. den Nutzer, der erwartet mit dem Backbutton zurück zu der eben benutzten Anwendung zu gelangen und diese jetzt evtl wieder neu startet und wieder CPU verbraucht.

Hier mein Verständnis zu den vorgeschlagenen Methoden:

Activity.finished();
Die Docu schreibt dazu:
„Call this when your activity is done and should be closed. The ActivityResult is propagated back to whoever launched you via onActivityResult(). “

Dieser Aufruf ist sinnvoll, wenn meine Activity eine Subactivity ist und ich die von mir verlangten Daten an die aufrufende Activity übergeben habe. Meine Activity wird nun nicht mehr gebraucht und ist auch nicht per Backbutton erreichbar. Meine Activity bekommt die niedrigste Prio und wird beim nächsten Bedarf aus dem Speicher entfernt.

finished()
Hat keine Auswirkungen auf eine Main-Activity also auf die erste steuernde Activity meines Programmes.

System.exit(0)
Würde ich nicht verwenden, denn damit umgehe ich das Android-Framework und halte mich nicht an den Lifecycle und riskiere Inkonsistenz im Lifecycle (kein Aufruf von onStop bzw. onDestroy)

Um dennoch schonend mit dem Speicher / Performance umzugehen, gibt es gute Tipps auf der Android Developer Seite:

http://developer.android.com/guide/practices/design/performance.html

Diese beinhaltet folgendes:
# Avoid Creating Objects
# Use Native Methods
# Prefer Virtual Over Interface
# Prefer Static Over Virtual
# Avoid Internal Getters/Setters
# Cache Field Lookups
# Declare Constants Final
# Use Enhanced For Loop Syntax With Caution
# Avoid Enums
# Use Package Scope with Inner Classes
# Avoid Float

* Ein Android Programm besteht aus einer oder mehreren Activities.

Antworten
Max B.
  • Forum-Beiträge: 727

21.05.2011, 19:15:30 via Website

Ich bin ein ziemlich neuer Benutzer von Android und deshalb möchte ich wissen, ob ich das genannte am PC oder am Handy eingeben muss?
vielleicht Tutorial : D

http://i.imgur.com/V9SDw.jpg Blau und Weiß - Ein Leben lang Straubing Tigers instagram: http://www.instagram.com/maxsobored

Antworten
Gelöschter Account
  • Forum-Beiträge: 281

21.05.2011, 19:53:45 via Website

Also zu System.exit(0) sag ich jetzt mal gar nichts, das ist einfach d...

Ansonsten würde ich mich um das "Beenden" meiner Apps nicht aktiv kümmern, dazu gibt es die entsprechenden Life-Cycle-Callbacks (onPause, onDestroy, usw...). Und dort gilt einfach nur - behave nicely, also Status ordentlich sichern, alles, was man irgendwo an Listenern registriert hat, deregistrieren, Services un-binden und stoppen und so weiter. Und in den entsprechenden gegenteiligen Callbacks (onResume) einfach umgekehrt.

Kurzum - sorgt doch einfach dafür, dass das Betriebssystem die App beenden oder pausieren kann, wann und wie es das für richtig hält.

Antworten
Frank M.
  • Forum-Beiträge: 20

11.09.2012, 09:04:59 via Website

Hallo,

sauber beenden mit Beenden-Button und Menüpunkt "beenden" ist schön und gut.

Wenn der User aber nicht wie vorgesehen beendet,
sondern einfach auf die Hardware-Taste mit dem Häusle tippt,
dann läuft die Anwendung im Hintergrund weiter.

Ist es möglich den Code so zu gestalten, dass die gesamte App beim Häusle-Button beendet wird?

PS: Bis jetzt habe ich in den Stopp-Button (Menüpunkt) und in onDestroy() (Listener-Beerdigung)
jeweils finish(); und System.exit(0); reingepackt.

mit vorauseilenden Dank
der Frank

Antworten
Florian B.
  • Forum-Beiträge: 284

11.09.2012, 09:56:13 via Website

So viel ich weiß, kann man den Home Button nicht überschreiben.

Es stellt sich auch nach wie vor die Frage, warum die App unbedingt geschlossen werden muss und man gegen das Android Framework arbeiten muss.

Antworten
Rafael K.
  • Forum-Beiträge: 2.359

11.09.2012, 10:42:03 via Website

Frank Mehlhop
PS: Bis jetzt habe ich in den Stopp-Button (Menüpunkt) und in onDestroy() (Listener-Beerdigung)
jeweils finish(); und System.exit(0); reingepackt.
Lies dir mal die Doku zum Thema Activity Lifecycle durch.
Beim Minimieren der App wird die onPause() Methode aufgerufen.
Bevor die App aus dem Speicher fliegt, wird noch onSaveInstanceState() aufgerufen.
Das ist das einzige was das Framework garantiert.
onStop(), onDestroy() usw. kann aufgerufen werden, muss aber nicht, wenn z.B. dringend Speicher freigeräumt werden muss.

— geändert am 11.09.2012, 10:42:26

Antworten
Frank M.
  • Forum-Beiträge: 20

11.09.2012, 12:14:26 via Website

Rafael K.
Beim Minimieren der App wird die onPause() Methode aufgerufen.
Gibt es die Möglichkeit dem Betriebssystem mitzuteilen, dass mein einem onPause() meiner App finish() ausgeführt werden soll?

Antworten
Florian B.
  • Forum-Beiträge: 284

11.09.2012, 12:32:01 via Website

Kannst du uns mal erklären, warum du die App unbedingt beenden möchtest? Das muss ja einen Grund haben.

Antworten
Gelöschter Account
  • Forum-Beiträge: 694

11.09.2012, 13:54:53 via Website

Ich häng mich auch mal ran:

Eigentlich sollte es für einen Entwickler selbstverständlich sein das er alles aufräumt was er zuvor erschaffen hat. Wenn ich mir aber so manchen Code in den Schulungen so anschaue dann bekomme ich das kalte Grausen. Nach dem Motto "Irgendeiner wird schon hinter mir aufräumen" verlässt man sich auf viele Automatismen - vergisst aber allzu leicht das es Dinge gibt die werden eben nicht sofort aufgeräumt (z.B. ein laufender Task mit Netzwerkverbindungen, etc.).

Eben diese Nicht-Aufräumer fallen bei Android auf die Nase da Android noch einen Schritt weiter geht - die App wird nämlich nur dann wirklich geschlossen wenn das System das für nötig erachtet - nicht der Benutzer, nicht der Entwickler. Während die Activity schon längst beendet ist läuft ein Task, gestartet in der selben Activity, lustig weiter - denn der Prozess läuft ggfs. noch

Beendet wird jede Activity mit der folgenden Befehlsfolge - damit ist gewährleistet das aufrufende Activities oder Systembestandteile sauber mit dieser Activity umgehen:

1setResult(<z.B. RESULT_OK>);
2finish();

Das ist hier alles schon aufgeführt worden. Ich möchte mit ein paar Zitaten das Verhältnis - den "Vertrag" - zwischen Entwickler und dem Android System vielleicht etwas klarer machen:

* "[...] onPause() is where you deal with the user leaving your activity. Most importantly, any changes made by the user should at this point be committed [...]". Gefunden hier.

* "You should really think about not exiting the application. This is not how Android apps usually work.". Diese Aussage stammt von Romain Guy dem Android Mitentwickler, gefunden hier.

* "We did not want to require that users close applications when "done" with them. Such a usage pattern does not work well in a mobile environment, where usage tends to involve repeated brief contact with a wide variety of applications throughout the day.". Diese Aussage stammt von Frau Hackborn der Android Framework Entwicklerin, gefunden hier.

Eine App mit einem Exit Button hat etwas zu verbergen. Entweder ist es eine App die von einer anderen Plattform, in Unkenntnis des Android Zielsystems, 1:1 übertragen wurde oder sie ist nicht sauber programmiert und lässt im exit() aufräumen, nämlich all das was der Entwickler selbst nicht aufräumen will oder all das von dem er nicht wusste wie es richtig geht.

— geändert am 11.09.2012, 14:02:52

Gelöschter Account

Antworten
André
  • Forum-Beiträge: 77

11.09.2012, 14:51:17 via Website

Wenn man ordentlich aufräumt, gibt es keinen Gund seine Activity selbst zu beenden, wenn man nicht gerade eine Anwendung hat, die irgendwann mit dem was sie tut "fertig" ist, oder man sie "gegen den Willen des Nutzers" beenden will, z.B. nach einer Fehlermeldung.

Als grobe Definition, was in einer normalen Activity "ordentlich aufräumen" bedeutet, würde ich persönlich folgendes sehen:

* Nachdem onStop() aufgerufen wurde, läuft kein Thread der Anwendung mehr und sie hat keine aktiven BroadcastReceiver.

Wenn man das befolgt, verbraucht die Activity keine CPU ( = Batterie) wenn sie nicht sichtbar ist, und stört damit auch nicht. Sollte das System zu wenig Speicher haben, wird es die Activity selbst beenden. Der Vorteil, wenn man seine Activity dabei nicht selbst beendet, ist dass ein erneutes Wechseln des Benutzers zu der Activity sehr schnell geht, da der Zustand und die Daten in der Anwendung noch komplett vorhanden sind und nicht neu geladen werden müssen.

Antworten
Frank M.
  • Forum-Beiträge: 20

11.09.2012, 14:51:52 via Website

Florian B.
Kannst du uns mal erklären, warum du die App unbedingt beenden möchtest?
Die App produziert Töne zu gegebenen Anlässen.
Wenn der User die App wegklappt (mit dem Häusle) und es piept weiter, dann denkt der doch, was'n das für'n Mist.

wenn onPause(); nicht void wäre, sondern vielleicht ein boolean für Pause Ja ode Nein geben würde, könnte ich ich die Tonausgabe in diese Abfrage packen. Ist aber nicht.

Darum suche ich weiter,
wie kann entweder die App mit dem Häusle ganz beendet werden
oder wie kann ich in der App abfragen ob die App auf onPause() steht?

— geändert am 11.09.2012, 15:00:06

Antworten
André
  • Forum-Beiträge: 77

11.09.2012, 14:54:28 via Website

Frank Mehlhop
Florian B.
Kannst du uns mal erklären, warum du die App unbedingt beenden möchtest?
Die App produziert Töne zu gegebenen Anlässen.
Wenn der User die App wegklappt (mit dem Häusle) und es piept weiter, dann denkt der doch, was'n das für'n Mist.

Das ist kein Grund die App zu beenden, sondern sie besser zu implementieren. Einfache Idee: ein Flag isRunning welches in onStart() auf true gesetzt wird, in onStop() auf false, und die Töne werden nur abgespielt wenn das Flag auf true gesetzt ist.

Als ernsthafter Vorschlag: die "gegeben Anlässe" sind vermutlich Events die per BroadcastReceiver empfangen werden? Die solltest du eh in onStop() deaktivieren.

— geändert am 11.09.2012, 14:55:48

Antworten
Frank M.
  • Forum-Beiträge: 20

11.09.2012, 15:03:00 via Website

André
die "gegeben Anlässe" sind vermutlich Events die per BroadcastReceiver empfangen werden? Die solltest du eh in onStop() deaktivieren.

Ne, es sind Sensordaten, die akustisch ausgewertet werden.

Antworten
Frank M.
  • Forum-Beiträge: 20

11.09.2012, 15:05:39 via Website

André
ein Flag isRunning welches in onStart() auf true gesetzt wird, in onStop() auf false, und die Töne werden nur abgespielt wenn das Flag auf true gesetzt ist.

Ich habe noch nie mit Flag's gearbeitet.
Ich vermute, das ginge auch mit onPause() statt mit onStop()?!?
Weil wenn onStop() greift, dann habe ich das Problem ja schon gar nicht mehr.

Antworten
Gelöschter Account
  • Forum-Beiträge: 694

11.09.2012, 15:08:08 via Website

Kleine Korrektur: onResume sowie onPause sind das richtige Pärchen. onStart/onStop brauchst Du normalerweise nie.

Die Activity ist außerhalb onResume/onPause nicht sichtbar. BroadcastReceiver z.B. außerhalb der beiden sind sinnlos da sie entweder Töne oder Bildschirmausgaben produzieren. Wer will das schon von einer nicht mehr sichtbaren Activity.

Antworten
André
  • Forum-Beiträge: 77

11.09.2012, 15:11:07 via Website

Frank Mehlhop
Ich habe noch nie mit Flag's gearbeitet.
Ich vermute, das ginge auch mit onPause() statt mit onStop()?!?
Weil wenn onStop() greift, dann habe ich das Problem ja schon gar nicht mehr.

Das hört sich sehr merkwürdig an. onPause() wird aufgerufen, wenn eine andere App den Focus erhält, aber deine App noch auf dem Bildschirm sichtbar ist. In dem Fall wäre wohl sinnvoll, wenn die Sounds noch abgespielt werden.
Wenn du den Home Button drückst, wird IMMER auch onStop() aufgerufen.

Aus deinen Posts würde ich mal herauslesen, dass du in deiner App den Activity Lifecycle nicht korrekt umsetzt. Vielleicht mal hier nachlesen: http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

Frank M.

Antworten
André
  • Forum-Beiträge: 77

11.09.2012, 15:12:15 via Website

Harald Wilhelm
Die Activity ist außerhalb onResume/onPause nicht sichtbar. BroadcastReceiver z.B. außerhalb der beiden sind sinnlos da sie entweder Töne oder Bildschirmausgaben produzieren. Wer will das schon von einer nicht mehr sichtbaren Activity.

Das stimmt so nicht.

"If an activity has lost focus but is still visible (that is, a new non-full-sized or transparent activity has focus on top of your activity), it is paused. A paused activity is completely alive (it maintains all state and member information and remains attached to the window manager), but can be killed by the system in extreme low memory situations.

If an activity is completely obscured by another activity, it is stopped. It still retains all state and member information, however, it is no longer visible to the user so its window is hidden and it will often be killed by the system when memory is needed elsewhere."

http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

— geändert am 11.09.2012, 15:19:20

Antworten
Florian B.
  • Forum-Beiträge: 284

11.09.2012, 15:21:11 via Website

Frank Mehlhop
André
die "gegeben Anlässe" sind vermutlich Events die per BroadcastReceiver empfangen werden? Die solltest du eh in onStop() deaktivieren.

Ne, es sind Sensordaten, die akustisch ausgewertet werden.

Ob die Daten nun per BroadcastReceiver empfangen oder eine Sensor direkt in der App ausgelesen wird, letztendlich kann man beides in der onPause() /onStop() abstellen bzw. ab/-unterbrechen

Lange Rede kurzer Sinn, man kann den Home-Button nicht wirklich überschreiben.

— geändert am 11.09.2012, 15:22:35

Frank M.

Antworten
Frank M.
  • Forum-Beiträge: 20

11.09.2012, 15:23:06 via Website

Kann ich innerhalb des Programms herauslesen,
ob die App im onPause()-Modus (gar im onStop()-Modus) ist oder nicht?

Antworten
André
  • Forum-Beiträge: 77

11.09.2012, 15:25:28 via Website

Frank Mehlhop
Kann ich innerhalb des Programms herauslesen,
ob die App im onPause()-Modus (gar im onStop()-Modus) ist oder nicht?

Das kannst du dir einfach merken. Aber wie gesagt, das wäre nur ein workaround, das eigentliche Problem ist dass du den Acivity Lifecycle missachtest.

Vermutlich liest du die Sensordaten in einem Thread per Timer aus, und wenn du das nicht stoppst, wenn deine App in den Hintergrund kommt (onStop()), wird man sie ganz schnell wieder deinstallieren. Nicht wegen der Töne, sondern weil sie dann unnötig Batterie frisst.

— geändert am 11.09.2012, 15:26:51

Antworten
Frank M.
  • Forum-Beiträge: 20

11.09.2012, 15:37:39 via Website

André
Das kannst du dir einfach merken.
...meinst Du ich merke mir ob die App auf onPause() steht, oder was?
(mit Flag's...?!)

André
Vermutlich liest du die Sensordaten in einem Thread per Timer aus,
Nein, ich lese die Sensordaten per Listener aus.

André
und wenn du das nicht stoppst, wenn deine App in den Hintergrund kommt (onStop()), ...
Na das ist doch genau das Thema!
Die App ist am laufen und der User will mit Home beenden.
S'is aber nicht beendet, sondern der Thread läuft weiter
und das will ich vermeiden.

Antworten
Gelöschter Account
  • Forum-Beiträge: 694

11.09.2012, 15:40:32 via Website

André
Das stimmt so nicht.

Dann ist halt diese Android Developer Seite falsch.

"onPause() is where you deal with the user leaving your activity."

Wie auch immer, ich habe in keiner meiner Anwendungen onStop()/onStart() in Benutzung und halte mich seit Jahren an die o.a. Regeln.

Ich wollte das gerade noch mit den SDK Samples unterfüttern und bin direkt beim ersten Sample (MapsDemo) über folgendes gestolpert - da ist dann jegliche Argumentation für die Katz ;-)

1@Override
2 protected void onResume() {
3 super.onResume();
4 mSensorManager.registerListener(mRotateView,
5 SensorManager.SENSOR_ORIENTATION,
6 SensorManager.SENSOR_DELAY_UI);
7 mMyLocationOverlay.enableMyLocation();
8 }
9
10 @Override
11 protected void onStop() {
12 mSensorManager.unregisterListener(mRotateView);
13 mMyLocationOverlay.disableMyLocation();
14 super.onStop();
15 }

Antworten
André
  • Forum-Beiträge: 77

11.09.2012, 15:52:16 via Website

Das sind halt auch nur Menschen bei Google ;)

Harald Wilhelm
Dann ist halt diese Android Developer Seite falsch.

"onPause() is where you deal with the user leaving your activity."

EDIT: das widerspricht dem Rest nicht. Der Benutzer verlässt die Activity, sie ist aber noch sichtbar.

Tatsächlich ist mir in der Praxis aber kein Fall bekannt, wo die App nicht mehr den Focus hat, aber noch sichtbar ist. Sowas wie ein Popup Fenster des Systems gibt es ja bei Android eigentlich nicht. (Lustigerweise lässt der Aufruf des Task-Managers die App nicht pausieren.)
Von daher sollte es in der Praxis wohl egal sein, ob man sich an onPause() oder onStop() ranhängt, da eh immer beides direkt nacheinander aufgerufen wird.

Die Idee im Lifecycle wäre aber eher, dass man in onPause() z.B. ein Spiel anhält (der Benutzer macht ja gerade was anderes), aber noch ausgibt (es ist ja noch (teilweise) sichtbar). Erst in onStop() ist die App dann wirklich nicht mehr zu sehen und man sollte sie stilllegen.

Ich habe grad den GLSurfaceView.Renderer angeschaut, der reagiert auch auf pause/resume. Das ist wohl alles noch nicht so ausgereift.

— geändert am 11.09.2012, 15:57:21

Antworten
André
  • Forum-Beiträge: 77

11.09.2012, 15:55:32 via Website

Frank Mehlhop
Na das ist doch genau das Thema!
Die App ist am laufen und der User will mit Home beenden.
S'is aber nicht beendet, sondern der Thread läuft weiter
und das will ich vermeiden.

Genau darum geht's. Einfach in onStop() den Listener stoppen (unregisterReceiver() oder whatever), dann tut die App nichts wenn sie nicht sichtbar ist und alle sind glücklich. (Vorausgesetzt das Registrieren des Listeners passiert in onStart(), was auch jetzt schon so sein sollte.)

Die Funktion des Home-Button zu überschreiben wäre auch ziemlicher Müll. Und ist in keiner Situation nötig, außer man will einen zusätzlichen Button für seine Anwendung gewinnen ;)

Antworten