Lär dig Java för Android-utveckling Mer om Inre klasser

Den här snabba lektionen diskuterar ett antal tips för att arbeta med inre klasser i Java. Denna lektion är en del av en pågående serie av handledning för utvecklare som lär sig Java för att utveckla Android-applikationer.

Vad är (Anonymous) Inner Classes?

I Java kan klasser nästas i varandra för att organisera data och funktionalitet på ett ordnat sätt. Anonyma inre klasser är i grunden utvecklare stenografi, vilket gör det möjligt för utvecklaren att skapa, definiera och använda ett anpassat objekt i taget. Anonyma inre klasser används ofta i Android för att definiera hanterare för kontroller, definiera och starta nya trådar och skapa och returnera anpassade objekt i metoder utan att röra kod med onödig inställning.

För en grundlig diskussion om kapslade och inre klasser, inklusive anonyma inre klasser, se vår handledning kallad Learn Java for Android Development: Inner Classes

Öppna externa variabler med det slutliga sökordet

Ibland vill du få tillgång till information som är tillgänglig utanför den inre klassen. Tänk på följande exempel. Du har en skärm med två kontroller: en knapp och en textvy. Varje gång användaren klickar på knappkontrollen uppdateras TextView-kontrollen med den aktuella tiden. Inom Aktivitetsklassen associerad med denna layout, du skulle kunna implementera denna funktionalitet enligt följande:

 Knapp myButton = (Button) findViewById (R.id.ButtonToClick); MyButton.setOnClickListener (new View.OnClickListener () public void onClick (Visa v) SimpleDateFormat formatter = ny SimpleDateFormat ("h: mm: ss a"); String strWhen = formatter.format (nytt datum ()); TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); myTextview.setText ("Clicked at" + strWhen);); 

Ovanstående kod kommer att köras och uppträda som förväntat. Låt oss dock säga att du verkligen ville förklara TextView-kontrollen utanför den inre klassen och använda den till andra ändamål också. Kanske skulle du försöka göra det istället:

 TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); Knapp myButton = (Button) findViewById (R.id.ButtonToClick); myknot setText ("Clicked at" + strWhen);); 

Tyvärr kommer det inte att kompileras. I stället får du kompileringsfelet "Kan inte referera till en icke-slutlig variabel myTextview i en inre klass definierad i en annan metod". Som felet föreslår, behöver du göra TextView-variabelns slutliga, så att den är tillgänglig inom den inklassade metoden onClick ():

 sista TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); Knapp myButton = (Button) findViewById (R.id.ButtonToClick); myknot setText ("Clicked at" + strWhen);); 

Denna kod kommer verkligen att kompilera och köras som förväntat.

Arbetar med slutliga variabler i Java

Genom att göra TextView-variabeln slutgiltig i föregående exempel har du gjort den tillgänglig för den anonyma inre klassen (eller någon inre klass som definieras inom dess räckvidd, för den delen). Här är några andra saker att veta om slutliga variabler:

  • Du kan inte ändra värdet (r-värde) för en slutlig variabel. Om du till exempel försökte tilldela variabeln myTextview till en annan kontroll inom metoden onClick () i den inre klassen, skulle du få kompileringsfelet. Den slutliga lokala variabeln myTextview kan inte tilldelas, eftersom den definieras i en omslutande typ. ”
  • Du kan ringa en slutlig variabels metoder, förutsatt att du har tillgång. Det här låter oss ringa till TextViews setText () -metod. Detta ändrar inte värdet av variabeln myTextview, det ändrar helt enkelt vad som visas på skärmen - en subtil men viktig skillnad. (Anledningen till detta är helt enkelt att hänvisningen till objektet inte kan förändras, men själva objektet kan förändras genom dess metoder.)
  • En slutlig variabels värde behöver inte vara känd vid sammanställningstiden, medan en statisk variabel är känd vid sammanställningstiden.
  • Det slutliga sökordet kopplas ofta ihop med den statiska variabeln (ett fält eller en variabel som är kopplad till alla instanser av en klass i stället för en enda instans) för att skapa en konstant för användning inom din ansökan, som i: offentlig statisk slutlig String DEBUG_TAG, som används för LogCat-loggning under hela din aktivitet.

Inre klasser och "Denna" variabeln

I Java kan du använda specialen detta referens hänvisar till objektets specifika förekomst. Så vad händer när du har en klass med en inre klass, eller, för den delen, en anonym inre klass? Nåväl kan den inre klassen få tillgång till den speciella denna förekomst av den omgivande klassen, och den har även denna referens. För att komma åt den här förekomsten för den inre klassen, använd helt enkelt denna syntax. För att få tillgång till den här instansen av den omgivande klassen måste du tacka namnet på den bifogade klassen, sedan en punkt, då detta. Till exempel:

 MyEnclosingClass.this 

Ta en titt på det fullständiga genomförandet av den anonyma inre klassen, som diskuterats ovan, i det fullständiga sammanhanget av dess omslutande klass, här kallad ClassChaosActivity:

 paketet com.androidbook.classchaos; importera java.text.SimpleDateFormat; importera java.util.Date; importera android.app.Activity; importera android.os.Bundle; importera android.util.Log; importera android.view.View; importera android.widget.Button; importera android.widget.TextView; offentlig klass ClassChaosActivity utökar aktivitet public static final string DEBUG_TAG = "MyLoggingTag"; / ** Kallas när aktiviteten skapas först. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); sista TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); Knapp myButton = (Button) findViewById (R.id.ButtonToClick); myknot setText ("Clicked at" + strWhen); Log.v (DEBUG_TAG, "detta klassnamn:" + this.getClass (). getName ()); Log.v (DEBUG_TAG, "detta utökar gränssnittet namnges:" + this. getClass (). getInterfaces () [0] .getName ()); Log.v (DEBUG_TAG, "detta Inkl. klassnamn:" + this.getClass (). getEnclosingClass (). getName ()); Log.v (DEBUG_TAG , "Detta är anonym klass?" + this.getClass () .AnonymousClass ()); Log.v (DEBUG_TAG, "ClassChaosActivity.this klassnamn:" + ClassChaosActivity.this.getClass (). getName ()); v (DEBUG_TAG, "ClassChaosActivity.this Super Class namn:" + ClassChaosActivity.this.getClass (). getSuperclass (). getName ()); Log.v (DEBUG_TAG, "ClassChaosActivity.this Är anonym klass?" + ClassChaosActivity.this .getClass (). isAnonymousClass ()););  

Logutmatningen för knappklicket fortsätter enligt följande:

 10-24 18: 18: 53.075: VERBOSE / MyLoggingTag (751): detta klassnamn: com.androidbook.classchaos.ClassChaosActivity $ 1 10-24 18: 18: 53,085: VERBOSE / MyLoggingTag (751): detta utökar gränssnittet heter: android .view.View $ OnClickListener 10-24 18: 18: 53.085: VERBOSE / MyLoggingTag (751): detta Insläppande klassnamn: com.androidbook.classchaos.ClassChaosActivity 10-24 18: 18: 53.095: VERBOSE / MyLoggingTag (751): Detta är anonym klass? sant 10-24 18: 18: 53.095: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Klassnamn: com.androidbook.classchaos.ClassChaosAktivitet 10-24 18: 18: 53.105: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Super Klassnamn: android.app.Activity 10-24 18: 18: 53.105: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Är anonym klass? falsk 

Som du kan se, hänvisar det här sökordet till "närmaste" klassen - den inre klassen. Även om den inre klassen är anonym, ger Java det ett antal ClassChaosActivity $ 1 för att hålla reda på det. Även om det inte är användbart för utvecklare i sig, visar detta att den anonyma inre klassen behandlas som någon annan klass internt. Under tiden får vi tillgång till den omgivande klassexemplet med hjälp av ClassChaosActivity.this syntax.

Slutsats

I den här snabba lektionen har du lärt dig flera tips som hjälper dig att använda inre klasser och anonyma innerklasser mer skickligt. Du lärde dig att inre klasser kan få tillgång till variabler deklarerade utanför deras räckvidd, förutsatt att variablerna är markerade som slutliga och därför oföränderliga. Du lärde dig också om den speciella syntax som är relaterad till det här sökordet när det gäller att få tillgång till data från den inre klassens instans, såväl som att den omsluter klassens instansdata.

Om Författarna

Mobila utvecklare Lauren Darcey och Shane Conder har medverkat flera böcker om Android-utveckling: en fördjupad programmeringsbok med titeln Android Wireless Application Development och Sams TeachYourself Android Application Development inom 24 timmar. När de inte skriver, spenderar de sin tid på att utveckla mobil mjukvara hos sina företag och tillhandahålla konsulttjänster. De kan nås via e-post till [email protected], via deras blogg på androidbook.blogspot.com, och på Twitter @ androidwireless.

Behöver du hjälp med att skriva Android Apps? Kolla in våra senaste böcker och resurser!