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.
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
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.
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:
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.
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.
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.