Arkitekturen i Android-platformen
På grund af arkitekturen i Android – specielt at applikationerne ikke selv har kontrol over, hvornår og hvordan de lukkes ned og startes op – skal man skelne mellem den applikation, som brugeren oplever og den (Linux-)proces, som app’en kører i. Brugeren kan skifte væk fra app’en og hoppe tilbage igen og forventer at kunne tage den i brug fra det punkt, hun forlod den.
For at kunne understøtte en optimal brugeroplevelse, vil Android beholde så mange processer (med hver sin JVM) i hukommelsen, som der er plads til og så, når der er brug for mere hukommelse, fjerne (dræbe) den proces der vurderes som mindst vigtig for brugeroplevelsen.
Den dræbte proces får ikke mulighed for at gemme data eller rydde op, for oprydning ville forsinke den proces, der har brug for hukommelsen (typisk det program brugeren er i gang med). I stedet forventes det at Android-programmer rydder op og gemmer data, når de ikke mere er synlige, dvs. efter at onStop() er kørt færdigt (i Android 2.3.3 og tidligere kan det ske allerede efter onPause()).
Brugeren kan, ved at holde HJEM-knapppen nede, vælge mellem de senest brugte applikationer og ved ikke, at nogle af dem muligvis har fået dræbt deres proces. Vælger brugeren en af de apps, der er smidt ud af hukommelsen, vil Android starte en ny process (og en ny JVM) og genskabe applikationens tilstand.
Teknisk set sker det ved at Android kalder onCreate() på den forreste aktivitet (skærmbillede) i applikationen og giver den et Bundle med den gemte tilstand fra forrige gang (savedInstanceState). De parametre (intent’et), som den oprindelige aktivitet blev oprettet med, bliver også genskabt.
En måde at undgå at blive dræbt på er ved at starte en service. Da vil Android forsøge at undgå at slå processen ihjel, og, hvis f.eks. den aktive proces i forgrunden eller en af de andre processer med services kræver meget hukommelse, genstarte processen og servicen hurtigst muligt. Det siger sig selv, at det ikke giver nogen god brugeroplevelse, hvis der er for mange apps, der benytter sig af services.
Har man levende ikoner på hjemmeskærmen eller lytter efter broadcasts, bliver processen startet op fra tid til anden, men kan blive lukket lige så hurtigt igen, når broadcastet er blevet behandlet.
Og har man implementeret en content provider, kan ens process blive startet, når som helst nogen forespørger på de data, som app’en udbyder.
Et Androidprogram kan altså blive startet på en lang række måder, og den første stump programkode der køres kan derfor være meget forskellig afhængig af situationen.
Hvornår kan man risikere at starte i en frisk JVM?
Har man nogle data i hukommelsen, som man er afhængig af, skal man derfor tjekke for, om man kører på en frisk JVM, og data skal genindlæses/genskabes. Gør man det ‘lidt efter lidt’, når problemer opstår, vil man ende med et uoverskueligt program, for man kan risikere at starte op i en frisk JVM på et utal af måder.
Måderne er
- Brugeren starter programmet fra hjemmeskærmen (eller på en anden måde)
- Dvs. i alle de mulige start-skærmbilleder (aktiviteter med et <intent-filter>)
- Brugeren holder HJEM nede og vælger programmet mellem de seneste brugte programmer
- Dvs. der bør også være tjek i alle de interne aktiviteter i programmet
(medmindre Android aldrig vil starte dem op som de første fordi man ikke kan skifte tilbage til dem – det styrer man i manifestet hvor man bl.a. kan sætte android_noHistory=”true” eller android_launchMode=”singleTask”)
- Dvs. der bør også være tjek i alle de interne aktiviteter i programmet
- Alle andre indgangspunkter til programmet, dvs.
- Alle services (inkl. levende baggrunde)
- Alle broadcast receivers (inkl. alle levende ikoner)
- Alle content providers