Programmet i labb 3 består av fyra klasser:
Androidprogrammet består också av fyra klasser:
Resten av detta dokument beskriver klasserna LifeWorld och GameOfLife i mer detalj. Genomgående när vi nämner metoder och klasser i Android-programmet ger vi motsvarande namn i labb 3 inom "parenteserna" /.../, som i exemplet ImageView/JPanel/. Detta ska inte tolkas som att de två klasserna (eller metoderna) är identiska förutom namnet, men som att det finns en nära analogi.
LifeWorld är en subklass till ImageView /JPanel/, en biblioteksklass vars objekt kan användas som rityta.
Vad som ska ritas beskriver man genom att omdefiniera metoden onDraw /paintComponent/. Som tillståndsvariabler har vi i bägge fallen dels en referens till modellobjektet, dels höjd och bredd på en enskild cell. Androidklassen har också en tillståndsvariabel av typen Paint /Graphics/, den klass där man har metoder för att bestämma färg, typsnitt, linjetjocklek osv. I labb 3 behövde vi inte deklarera en sådan tillståndsvariabel, eftersom paintComponent till skillnad från onDraw har en parameter som ger ett lämpligt objekt. I övrigt är metoderna mycket lika.
LifeWorld implementerar också gränssnittet View.OnTouchListener /MouseListener/, som innehåller metoder för att reagera på mushändelser. I metoden onTouch /mouseClicked/ tar man rätt på vilken cell som klickats och byter tillstånd i denna cell. Slutligen begärs omritning av världen genom anrop av metoden invalidate /repaint/. Det är dock värt att notera att användargränssnittet här inte är så lyckat på en typisk telefon; de enskilda cellerna är för små för att man bekvämt ska kunna peka på dem med fingret på en touchskärm. Det finns många sätt man kan tänka sig för att förbättra detta, men vi lämnar det åt den intresserade.
Konstrueraren för klassen har främst som uppgift att initiera tillståndsvariablerna, skapa ett muslyssnarobjekt samt installera detta som lyssnare. Dessutom initieras bakgrundsfärgen till vit, så att endast svarta kvadrater behöver ritas. Androidvarianten blir något mer komplicerad än Swing-versionen:
Klassen LifeView skapar ett LifeWorld-objekt och tre knappar samt placerar dessa grafiskt i förhållande till varann med hjälp av ett BorderLayout-objekt. Exakt denna manager finns inte i Android, men liknande alternativ finns. Men det rekommenderade sättet att beskriva layout i ett Android-program är annorlunda; man gör detta i en separat XML-fil. Vi ger här XML-filen utan att kunna förklara allt:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <se.chalmers.cse.tda547.life.LifeWorld android:id="@+id/world" android:layout_width="match_parent" android:layout_height="wrap_content"/> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center"> <Button android:id="@+id/step" android:layout_height="wrap_content" android:layout_width="0.0dip" android:layout_weight="1.0" android:text="Step" /> <Button android:id="@+id/run" android:layout_height="wrap_content" android:layout_width="0.0dip" android:layout_weight="1.0" android:text="Run" /> <Button android:id="@+id/stop" android:layout_height="wrap_content" android:layout_width="0.0dip" android:layout_weight="1.0" android:text="Stop" /> <Button android:id="@+id/reset" android:layout_height="wrap_content" android:layout_width="0.0dip" android:layout_weight="1.0" android:text="Restart" /> </LinearLayout> </LinearLayout>
Vi har en vertikal linjär layout med två komponenter ovanför varandra. Den övre är en LifeWorld och den undre en ny linjär layout, denna gång horisontell, med fyra knappar. Varje enskild komponent har ett namn (en id); en sådan inleds med @+id/ och avslutas med en för varje komponent unik sträng. I övrigt beskrivs i filen hur komponenternas storlek ska anpassas till olika skärmstorlekar.
Notera också att vi lagt till en knapp jämfört med den tidigare versionen. Denna knapp (med texten Restart) skapar en ny slumpmässig population. Vi skulle gärna haft med den också i Swing-versionen, men en BorderLayout i Swing kan bara ha tre komponenter i bredd utan underlayouter …
Klassen GameOfLife är en subklass till Activity, den biblioteksklass som beskriver en interaktion mellan användaren och en app med ett GUI. Systemet kommer att anropa onCreate när appen startar. I denna metod görs all initiering. Vyn deklareras med setContentView(R.layout.main);, de olika komponenterna identifieras med sina namn, lyssnarklasser definieras och installeras i de olika knapparna samt en UITimer skapas med en lämplig lyssnare som parameter. Allt detta har en direkt motsvarighet i lab 3.
Er egen klass LifeModel kan användas som modellklass i en app som kan laddas ner till en Android-telefon. Som vanligt ger vi er all kod som behövs förutom modellklassen; ladda ner Life_android.zip och packa upp i en lämplig katalog. För beskrivning av hur man fortsätter, se beskrivningen av Mastermind.