The Android Launch Mode Animated CheatSheet

20. joulukuuta, 2018 – 6 min read

Ennen API 11:ttä käytimme aktiviteetteja, jotka näyttivät jokaisen uuden sivun näytöllä. Nyt Fragmenttien ja API 28:n navigointityökalujen avulla on täysin mahdollista tehdä hyvin monimutkainen sovellus vain yhdellä aktiviteetilla. Aktiviteetit ovat kuitenkin edelleen loistavia sovelluksen jakamiseen vaiheisiin ja prosesseihin. Ehkä haluat jakaa kaiken markkinoinnin yhteen aktiviteettiin ja pitää varsinaisen sovelluksen omana aktiviteettinaan. Ehkä haluat, että yksi osio on varattu jollekin ominaisuudelle, kuten chat-palvelulle. Aktiviteettien käynnistystapojen tunteminen auttaa sinua jakamaan nämä prosessit paremmin käyttäjien kannalta järkevillä tavoilla. Töissä istuessani en koskaan muistanut käynnistystapoja ulkoa, joten ajattelin kirjoittaa siitä blogin, animoida muutamia gif-kuvia havainnollistamaan käsitteitä ja jakaa sen sitten kaikkien kanssa.

Ennen kuin puhumme käynnistystiloista, ymmärrämme ensin tehtävän roolin. Tehtävä sisältää kokoelman aktiviteetteja, jotka on järjestetty pinoihin, joita kutsutaan backstackiksi. Tehtävän ensimmäinen käynnistettävä aktiviteetti on root-aktiviteetti. Painamalla takaisin-painiketta root-aktiviteetilla ei ainoastaan lopeteta aktiviteettia, vaan myös tehtävä ja mahdollisesti koko sovellus.

Sukelletaan nyt muutamiin käynnistystapoihin!

Asettakaamme, että sinulla on tehtävä, jonka root-aktiviteetti on nimeltään aktiviteetti A, ja käynnistät sitten uuden aktiviteetin nimeltä B, jolloin B työnnetään pinon yläosaan. Sanotaan nyt, että käynnistät toisen Activity B:n juuri luomastamme B:stä, sinulla on nyt kaksi Activity B:n instanssia pinossa päällekkäin. Jos käyttäjä painaa takaisin-painiketta, hän palaa Activity B:n toiseen instanssiin. Tämä voi olla käyttäjälle hyvin hämmentävää. Aktiviteettien pinoamista ja luomista päällekkäin riippumatta siitä, mikä on kyseessä, kutsutaan vakiokäynnistystilaksi. Jos aktiviteetin XML:ssä manifestissa ei ole määritetty käynnistystilaa, aktiviteetti käyttää vakiomuotoista käynnistystilaa.

Nyt kun olemme nähneet, miten vakiomuotoinen tila voi olla häiritsevä käyttäjälle, pystymme nyt ymmärtämään Yksittäinen päällimmäinen käynnistystila. Tämä käynnistystila estää samojen toimintojen eri instanssien pinoamisen päällekkäin. Oletetaan, että aktiviteetti B on yksittäinen huippu. Voimme määritellä laukaisutilat manifestissa näin:

///AndroidManifest.xml
<application
...>
<activity android:name=".Activity_A">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity> <activity android:name=".Activity_B" android:launchMode="singleTop"/> <activity android:name=".Activity_C"/>
<activity android:name=".Activity_D"/>
</application>

Jos siis nyt käynnistät aktiviteetin B aktiviteetista B, sen sijaan, että luot uuden instanssin B:stä ja pinotat sen vanhan B:n päälle, aikomus siirretään nykyiseen instanssiin B:stä. Ainoa tapa saada kaksi instanssia samasta aktiviteetista samassa tehtävässä on käynnistää eri aktiviteetti B:stä ja luoda sitten B tästä aktiviteetista. Single top -laukaisutilan pääkonsepti on se, että saman aktiviteetin kahta instanssia ei voi olla päällekkäin pinottuna.

Jos et halua saman single top -aktiviteetin kahta instanssia tehtävään käyttäessäsi single top -laukaisutilaa, voit välittää FLAG_ACTIVITY_CLEAR_TOP-vakiota intentissäsi. Havainnollistetaan, mitä tämä tekee: sanotaan, että aktiviteettipinosi on ABC (B on edelleen single top). Tässä käynnistystilassa todetaan, että aktiviteetti voi kuulua vain yhteen tehtävään kaikissa sovelluksen tehtävissä. Samoin kuin FLAG_ACTIVITY_CLEAR_TOP-käyttäytymisessä, jos pinosi on ABC ja käynnistät B:n (yksittäinen tehtävä) C:stä, ponnahdamme aina B:hen asti ja välitämme aikomuksen kyseiselle instanssille.

<activity android:name=".Activity_B" android:launchMode="singleTask"/>
>

>

>Mutta entäpäs, jos haluaisimmekin B:n olevan omassa tehtävässään? Tässä kohtaa tehtävän affiniteetti astuu kuvaan. Tehtäväaffiniteetin avulla voit määrittää, mihin tehtävään toiminto kuuluu. Oletusarvoisesti aktiviteetilla on sama tehtäväaffiniteetti kuin sen pääaktiviteetilla. Tehtäväaffiniteetin avulla voimme nyt erottaa aktiviteetit eri tehtäviin.

<activity android:name=".Activity_A"
android:taskAffinity="com.affinity.of.a">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity><activity android:name=".Activity_B"
android:launchMode="singleTask"
android:taskAffinity="com.affinity.of.b"
/>

Tässä aktiviteetilla A ja aktiviteetilla B on eri tehtäväaffiniteetit. Kun A luodaan tehtävässä 1, C käynnistetään A:sta. Oletusarvoisesti jokaisella aktiviteetilla on sama affiniteetti kuin sen juurella, joten olemme edelleen tehtävässä 1. Nyt B käynnistetään C:stä. B:llä on eri tehtäväaffiniteetti, joten se on nyt tehtävän 2 juuri, joka siirtyy etualalle. Jos B:stä käynnistetään uusi toiminto C, C kuuluu tehtävään 2, koska se on juuritoiminnon (tässä tapauksessa B:n) tehtäväaffiniteetti. Mutta entä jos nyt yritämme käynnistää A:n C:stä tehtävässä 2? Koska A:n affiniteetti on Tehtävä 1, siirrymme Tehtävästä 2 Tehtävään 1, ponnahdamme koko matkan takaisin Toimintoon A ja lopulta välitämme aikomuksen A:lle.

Yksittäisen Tehtävän (Single Task) tunteminen auttaa meitä ymmärtämään paremmin lopullista käynnistystapaa; Yksittäinen instanssi. Kuten Single Task, myös Single Instance -toiminto voi olla ainoa toiminto kaikissa tehtävissä. Erona näiden kahden välillä on se, että Activity with Single Instance voi olla myös tehtävän ainoa Activity.

<activity android:name=".Activity_B"
android:launchMode="singleInstance"
android:taskAffinity="com.affinity.of.b"
/>

Tässä esimerkissä Activity B:n käynnistystapa on Single Instance. Tehtävän 1 Activity A käynnistää Activity B:n. Tämä saa aktiviteetin B käynnistymään uudessa tehtävässä, joka asetetaan etualalle. Tämän jälkeen aktiviteetti B käynnistää aktiviteetin C. Koska Single Instance voi olla tehtävän ainoa aktiviteetti, C käynnistyy tehtävän 1 aktiviteetin A päälle, jolloin tehtävä 1 tulee etualalle.

Task affinityllä on myös merkitystä Single Instance -tilassa. Jos toiminnolla B ei ole tehtäväaffiniteettia, käyttäjä ei voi siirtyä takaisin tehtävään 1. Jos B:llä oli tehtäväaffiniteetti, käyttäjä voi siirtyä tehtävien 1 ja 2 välillä edestakaisin.

Käynnistystilojen tunteminen auttaa minua tekemään parempia UI/UX-kokemuksia käyttäjilleni ja jopa ratkaisemaan joitain päätä askarruttavia bugeja, toivottavasti näistä tiedoista on apua myös sinulle!

Tahdon antaa tunnustusta Anil Deshpanden CodeTutor youtube-sivulle, joka auttoi minua ymmärtämään käsitteen paremmin. Tässä on ensimmäinen seitsemästä aiheesta tehdystä videosta: https://www.youtube.com/watch?v=m8sf0UkJkxo

Jätä kommentti