1. Nimm jetzt an unserem 2. ADVENT-Gewinnspiel teil - Alle Informationen findest Du hier!

benötige non final - putExtra will final!

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von StefMa, 15.11.2011.

  1. StefMa, 15.11.2011 #1
    StefMa

    StefMa Threadstarter Gewerbliches Mitglied

    Beiträge:
    2,054
    Erhaltene Danke:
    413
    Registriert seit:
    16.10.2010
    und wieder grüßt das Murmeltier ;)

    In der Datenbank stehen Labels, die auf Buttons kommen und Zahlen, die beim Intent als putExtra übergeben werden.

    PHP:
    for(int i=0i<howLongi++)
                {
                    
    buttons[i] = new Button(this); 
                    
    buttons[i].setText(lab);
                    
    ll.addView(buttons[i], new LayoutParams(420LayoutParams.WRAP_CONTENT));
                    
    buttons[i].setOnClickListener(new View.OnClickListener()
                    {
                        public 
    void onClick(View v)
                        {
                            
    Intent myIntent = new Intent(v.getContext(), Internet.class);
                            
    myIntent.putExtra("internet"intnr);
                            
    startActivity(myIntent);
                        }
                    });

                    if(
    != howLong-1)
                    {
                        
    bttnLab.moveToNext();
                        
    lab bttnLab.getString(0);
                        
    intNum.moveToNext();
                        
    intnr intNum.getInt(0);
                    }
                } 
    intnr ist eine Zahl, die aus der Datenbank aus der entsprechenden ROW rausgelesen wird.
    In der if() kann man gut sehen, wie ich dann zum nächsten ROW hüpfe und intnr eine neue Zahl bekommt.

    Das Problem:
    putExtra() möchte ein final! Allerdings ist final schelcht, wenn ich den wärt ändern möchte :flapper:

    Hat dazu jemand eine Idee?!

    MfG Ice
     
  2. swordi, 15.11.2011 #2
    swordi

    swordi Gewerbliches Mitglied

    Beiträge:
    3,389
    Erhaltene Danke:
    441
    Registriert seit:
    09.05.2009
    wenn du vorher einfach ne neue final var deklarierst?

    final Integer tmp = new Integer(intr);

    oder sowas in die richtung
     
    StefMa bedankt sich.
  3. the_alien, 15.11.2011 #3
    the_alien

    the_alien Android-Lexikon

    Beiträge:
    1,559
    Erhaltene Danke:
    184
    Registriert seit:
    04.05.2009
    Java lernen :flapper:

    Deine anonyme innere Klasse braucht final weil sie sonst nicht weiß wie sie an den Wert kommen soll. Entweder das oder du definierst sie als Klassenvariable.
    Eine Methode kann nicht verlangen eine final Variable zu bekommen. Das existiert nicht in Java.
     
  4. StefMa, 15.11.2011 #4
    StefMa

    StefMa Threadstarter Gewerbliches Mitglied

    Beiträge:
    2,054
    Erhaltene Danke:
    413
    Registriert seit:
    16.10.2010
    Hallo,

    wenn ich eine Klassenvariable
    int intnr;
    mache, dann wird immer das letzte was ich hinzugefügt habe als intnr zu JEDEM Button hinzugefügt! oO
    Warum?

    MfG Ice
     
  5. DieGoldeneMitte, 15.11.2011 #5
    DieGoldeneMitte

    DieGoldeneMitte Android-Lexikon

    Beiträge:
    1,230
    Erhaltene Danke:
    256
    Registriert seit:
    05.02.2010
    Phone:
    Nexus 5X
    Tablet:
    Nexus 7 (2013)
    Wenn du eine Instanzvariable (Klassenvariablen sind die mit static -- das nur zur Info) hast, wird der Wert genommen, denn diese Variable zum Zeitpunkt hat, wenn der Callback gerufen wird.

    Wenn du in der Schleife (beim Erzeugen der Callbacks) immer wieder einen Wert an eine Variable zuweist, hat diese beim Aufruf der Callbacks natürlich den zuletzt zugewiesenen Wert.

    In deinem Fall wäre wohl ein Array fällig. -- und etwas Java Nachhilfe, wie the_alien schon sagt :D
     
  6. StefMa, 15.11.2011 #6
    StefMa

    StefMa Threadstarter Gewerbliches Mitglied

    Beiträge:
    2,054
    Erhaltene Danke:
    413
    Registriert seit:
    16.10.2010
    HI,

    also danke erstmal für die Antworten!

    Allerdings verstehe ich echt.. naja eigentlich kaum was oO
    Ich habe Grundlagen in Java - etwas mehr vielleicht - deswegen frage ich ja auch...

    Also nochmal zum mitschreiben:
    alien sagt, ich soll eine Klassenvariable machen:
    PHP:
    static int intnr;
    Wenn ich das mache, dann wird, wie ich schon geschrieben habe, nur immer die letzte ausgabe gemacht.

    DieGoldeneMitte will, dass ich ein array mache, sähe also so aus??:
    PHP:
    static int[] intnr;
    und dann entsprechend den rest intnr als array deklarieren..?
    Dann bekomme ich aber beim catch() einen error (Selbstgeschreibenes Toast ;))

    Also wie bitte soll ich das jetzt anstellen?

    MfG Ice
     
  7. swordi, 15.11.2011 #7
    swordi

    swordi Gewerbliches Mitglied

    Beiträge:
    3,389
    Erhaltene Danke:
    441
    Registriert seit:
    09.05.2009
    was wäre, wenn du aus der inner class deines listeners eine "anständige" klasse baust

    der gibst du dann den int paramter im construktor mit und setzt es dann in der onClick methode.
     
  8. Tom299, 16.11.2011 #8
    Tom299

    Tom299 Android-Experte

    Beiträge:
    602
    Erhaltene Danke:
    120
    Registriert seit:
    31.08.2011
    laß mal static weg und schreib private hin, dann sollte das klappen, oder google mal nach Klassenvariablen und Instanzvariablen in java.
     
  9. the_alien, 16.11.2011 #9
    the_alien

    the_alien Android-Lexikon

    Beiträge:
    1,559
    Erhaltene Danke:
    184
    Registriert seit:
    04.05.2009
    Ich glaube du hast nicht verstanden wie innere anonyme Klassen arbeiten.
    Lies dir den entsprechenden Part erst mal durch
    Java ist auch eine Insel – 6.12 Innere Klassen
     
  10. Fr4gg0r, 16.11.2011 #10
    Fr4gg0r

    Fr4gg0r App-Anbieter (Werbung)

    Beiträge:
    2,506
    Erhaltene Danke:
    447
    Registriert seit:
    21.12.2009
    Da muss ich widersprechen^^
    Dem Compiler/VM kann das eigentlich banane sein ob final oder nicht, es dient scheinbar lediglich dem Zweck, dass dem Programmierer bewusst ist, womit die innere Klasse arbeitet.

    Beweis:
    Code:
        public void fubar(long value){
            Button button = null;
            final long a = System.currentTimeMillis(); //blöde Konstantenoptimierung
            button.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    fubar(a);
                }
            });
        }
    disassembliert (teile ausgelassen):

    Die Methode fubar()
    Code:
    # virtual methods
    .method public fubar(J)V
        .locals 4
        .parameter "value"
    
        .prologue
        .line 8
        const/4 v2, 0x0
    
        .line 9
        .local v2, button:Landroid/widget/Button;
        invoke-static {}, Ljava/lang/System;->currentTimeMillis()J
    
        move-result-wide v0
    
        .line 10
        .local v0, a:J
        new-instance v3, Lde/tests/test2$1;
    
        invoke-direct {v3, p0, v0, v1}, Lde/tests/test2$1;-><init>(Lde/tests/test2;J)V
    
        invoke-virtual {v2, v3}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V
    
        .line 15
        return-void
    .end method
    Und die vom Compiler erstellte innere Klasse
    Code:
    .class Lde/tests/test2$1;
    # interfaces
    .implements Landroid/view/View$OnClickListener;
    
    
    # annotations
    .annotation system Ldalvik/annotation/EnclosingMethod;
        value = Lde/tests/test2;->fubar(J)V
    .end annotation
    
    # instance fields
    .field final synthetic this$0:Lde/tests/test2;
    
    .field private final synthetic val$a:J
    
    # direct methods
    .method constructor <init>(Lde/tests/test2;J)V
        .locals 0
        .parameter
        .parameter
    
        .prologue
        .line 1
        iput-object p1, p0, Lde/tests/test2$1;->this$0:Lde/tests/test2;
    
        iput-wide p2, p0, Lde/tests/test2$1;->val$a:J
    
        .line 10
        invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    
        return-void
    .end method
    
    
    # virtual methods
    .method public onClick(Landroid/view/View;)V
        .locals 3
        .parameter "v"
    
        .prologue
        .line 12
        iget-object v0, p0, Lde/tests/test2$1;->this$0:Lde/tests/test2;
    
        iget-wide v1, p0, Lde/tests/test2$1;->val$a:J
    
        invoke-virtual {v0, v1, v2}, Lde/tests/test2;->fubar(J)V
    
        .line 13
        return-void
    .end method
    Man kann sehr schön sehen, dass der Konstruktor geändert wird, und eine Kopie des Wertes bzw. bei Objekten die Referenz kopiert wird.
     
  11. DieGoldeneMitte, 17.11.2011 #11
    DieGoldeneMitte

    DieGoldeneMitte Android-Lexikon

    Beiträge:
    1,230
    Erhaltene Danke:
    256
    Registriert seit:
    05.02.2010
    Phone:
    Nexus 5X
    Tablet:
    Nexus 7 (2013)
    Ich sehe das so:

    Das mit dem final ist eine Hilfe genau für Leute wie der OP, die noch nicht durchdrungen haben, dass der Code in einer anonymen Klasse nicht zeitlich zwischen dem Code davor und dahinter ausgeführt wird.

    Eine nicht final Variable muss halt irgendwann "umkopiert" werden, weil der Scope der Definition beim Aufruf der anonymen Klasse in der Regel nicht mehr exisitert. Tja, und wann genau soll denn Kopiert werden? Das final macht daraus ein "egal wann, der Wert ändert sich ja eh nicht". :D
     
    Zuletzt bearbeitet: 17.11.2011
    StefMa und the_alien haben sich bedankt.
  12. the_alien, 17.11.2011 #12
    the_alien

    the_alien Android-Lexikon

    Beiträge:
    1,559
    Erhaltene Danke:
    184
    Registriert seit:
    04.05.2009
    Ist richtig, aber es ist so spezifiziert und dem Compiler ist es nicht egal. Von daher sind das Spitzfindigkeiten und man kann an diesem Thread -und anderen in diesem und jedem anderen Java Forum- sehen, dass es wirklich gut ist, dass es so gemacht wurde.
    Besser ein Fehler zur Compile- als ein Fehler zur Laufzeit.
     
    StefMa bedankt sich.
  13. StefMa, 17.11.2011 #13
    StefMa

    StefMa Threadstarter Gewerbliches Mitglied

    Beiträge:
    2,054
    Erhaltene Danke:
    413
    Registriert seit:
    16.10.2010
    Also so langsam fühle ich mich richtig schlecht in Java :/
    Was habe ich denn da für ein Thema ausgegraben, in dem Worte vorkommen, die ich noch nie in meinem leben gehört habe :scared:

    Btw: ich habs immer noch nicht hinbekommen und die verschiedenen Links zu "hilfeseiten" helfen mir auch nicht weiter...
     
  14. Son Goku, 17.11.2011 #14
    Son Goku

    Son Goku Android-Hilfe.de Mitglied

    Beiträge:
    55
    Erhaltene Danke:
    5
    Registriert seit:
    07.12.2010
    Hallo

    Ich würde das ganze so aufbauen (ungetestet):
    PHP:
    for(int i=0i<howLongi++) {
        
    buttons[i] = new Button(this);
        
    buttons[i].setText(lab);
        
    buttons[i].setId(intnr);
        
    ll.addView(buttons[i], new LayoutParams(420LayoutParams.WRAP_CONTENT));
        
        
    buttons[i].setOnClickListener(new View.OnClickListener() {
            public 
    void onClick(View v) {
                
    int intnr v.getId();
                
                
    Intent myIntent = new Intent(v.getContext(), Internet.class);
                
    myIntent.putExtra("internet"intnr);
                
    startActivity(myIntent);
            }
        });

        [...]

    Ich gebe dem Button eine ID. In diesem Fall benutze ich einfach den Wert, den du an deine neue Intent übergeben willst. Ich weiß zwar nicht, wo die Variable "intnr" deklariert wird, aber ich nehme mal an, du hast das VORHER gemacht.

    Im OnClick-Event brauchst du jetzt nur noch die ID auszulesen und schon weißt du, welcher Button genau gedrückt wurde.
     
    StefMa bedankt sich.
  15. Fr4gg0r, 17.11.2011 #15
    Fr4gg0r

    Fr4gg0r App-Anbieter (Werbung)

    Beiträge:
    2,506
    Erhaltene Danke:
    447
    Registriert seit:
    21.12.2009
    Ich finde bei Java sollte man schon wissen wie anonyme Klasse behandelt werden..
    Um auch mal was sinnvolles beizutragen:
    "Take away Lösung" ;)
    final int tmpI = i; (das kommt natürlich vor setOnClickListener)
    und dann intent.putExtra("internet", tmpI);
    Ist prinzipiell das gleiche wie swordi geschrieben hat.
     
    StefMa bedankt sich.
  16. StefMa, 17.11.2011 #16
    StefMa

    StefMa Threadstarter Gewerbliches Mitglied

    Beiträge:
    2,054
    Erhaltene Danke:
    413
    Registriert seit:
    16.10.2010
    Öh lol! oO
    Ich bin ein Vogel.. danke euch allen :D... (danke klicke werden gleich verteilt xD)

    Mit Fr4gg0r bzw sowrdis hilfe hats geklappt!

    Aber eine frage habe ich noch:
    Wieso kann die Variable tmpl mehrmals deklariert werden?
    Denn die schleife geht ja mehrmals durch.. also wird immer wieder final int tmp gesagt... Wie funktioniert dass den nu bitte?

    MfG Ice
     
  17. the_alien, 18.11.2011 #17
    the_alien

    the_alien Android-Lexikon

    Beiträge:
    1,559
    Erhaltene Danke:
    184
    Registriert seit:
    04.05.2009
    Die Variable existiert nur in der Schleife. Ist der Schleifendurchlauf beendet wird sie weggeworfen und danach eine neue erstellt.
     

Diese Seite empfehlen