Thread, Handler,...

  • Hallo, möchte ein kleines Spiel erstellen weiß aber nicht genau wie ich das umsetzen kann.


    Ich habe mehrere Buttons auf meinem Spielfeld. In Runde 1 soll ein zufälliger Button die Farbe ändern und schlieslich vom Benutzer gedrückt werden. In Runde zwei soll wieder der erste Button die Farbe ändern und anschliesend ein zweiter, woraufhin beide in der richtigen Reihenfolge gedrückt werden müssen.
    In Runde 3 dann eben mit 3 Buttons, in Runde 4 mit 4, usw bis der Benutzer einen Fehler macht.


    Kann mir jemand einen Tipp geben wie sich das möglichst einfach umsetzen lässt? Hab mich ein wenig eingelesen und denke mit Threads und Handlern sollte das gehen oder? Allerdings blicke ich da noch nicht so ganz durch. Eine kleine Hilfe wäre sehr nett.

  • So in der Art hab ich mir das auch überlegt. Aber wie bekomme ich es hin dass die Buttons verzögert 'gemalt' werden? In Runde 5 werden ja z.B 5 Buttons gemalt und ich möchte immer zwischen jedem Button etwa 3 Sekunden Pause haben...

  • Hab jetzt mal bisschen rumprobiert.


    Die unten stehende Methode soll mir zunächst mal nur die Buttons 'malen' und dazu einen Sound abspielen. LautAusgeben() erledigt dass für jeden einzelnen Button indem ich einen bestimmten Wert mitgebe. Diese Werte habe ich zufällig in einem Array angelegt.


    Die Sounds werden auch richtig abgespielt, sprich die Methode funktioniert. Allerdings werden die Buttons auf dem UI nicht angezeigt. Erst der letzte Button wird wieder angezeigt sobald run durchgelaufen ist. Ich möchte aber das zu jedem Sound der jeweilige Button angezeigt wird, sprich das UI müsste während run läuft nach jedem Schleifendurchlauf aktualisiert werden...


    Bitte verurteilt mich ned. Bin was Threads, usw angeht absoluter Neuling... ;)

  • Das klingt jetzt aber nach einem sehr konstruierten Fall ohne wirklich sinnvollen Hintergrund.


    Was soll dir das bringen?
    Zumal du einen gewaltigen Fehler machst: UI im Hintergrund manipulieren wollen.
    Du darfst Interaktionen mit UI Elementen nur im MainThread oder UI Thread machen.
    Was du dort tust ist Folgendes:


    Du erstellst dir eine Referenz auf deinen UI Thread.
    Du erstellst dir eine Runnable, die den Thread schlafen legt, nen Sound abspielt und den Thread noch mal schlafen legt.
    Du startest dein Runnable verzögert auf dem UI Thread.


    Dieses gesamte Konstrukt könntest du einfach einsparen und die Schleife direkt in der buttons_zeichnen() durchlaufen.
    So hast du das Ganze zwar etwas verkompliziert, aber im Endeffekt nix daran geändert.


    Für so etwas sind Threads vermutlich der falsche Weg.
    Ein Thread sorgt dafür, dass irgendwas getan wird und dein UI nicht blockiert.
    Du möchtest aber, dass dein UI blockiert.
    Denn solange du die Farbe(n) deines Buttons aufleuchten lässt soll der User ja nicht herumpfuschen können.


    Als erster Punkt solltest du auf jeden Fall zuerst die Buttons erstellen und anzeigen, bevor du irgend etwas Anderes tust.
    Idealerweise speicherst du dir die Referenz dieser Buttons in einer List.
    Im 'Random'-Bereich lässt du dir dann einfach den Button an der Position der Random-Variable ausgeben, färbst ihn ein, wartest ein bisschen, färbst ihn zurück.
    (Hast du noch eine weitere Liste mit Integern kannst du dort deine Random-Variable reinpacken. Dann siehst du später auch, ob richtig geraten wurde.)


    Allerdings finde ich, dass Threading da ein völlig unsinniger Ansatz ist. Du brauchst es schlicht nicht und andererseits hindert es dich offenbar auch.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Okay, zu 100% kann ich dir natürlich nicht folgen. Bin doch noch ein ziemlicher Noob :D
    Dann vergess ich das mit Threads erstmal...



    Mein Problem stellt eigentlich nur das Zeichnen der Buttons + das gleichzeitige Abspielen der Sounds dar.
    Ich habe momentan vier Buttons welche auf invisible gestellt sind.
    An Array[0] steht dann z.B ne 4 und ich möchte die Methode buttonZeichnen(4) aufrufen in welcher Button4 auf visible gesetzt wird und der Sound abgespielt wird.


    An Array[1] steht dann z.B die 2 und in Runde 2 möchte ich dann buttonZeichnen[4] und buttonZeichnen[2] aufrufen. Das ganze geht dann in Runde 3 mit 3 Buttons,usw...


    Wenn ich das ganze über eine Schleife mache werden beide Buttons nahezu zeitgleich angezeigt deswegen müsste ich die Schleife praktisch einfach verzögern...
    Allerdigs weiß ich überhaupt nicht wie ich das anstellen soll. Daher hab ich da mit Threads ein wenig rumprobiert

  • Hoi,


    also ich hätte für jeden Button einen AsyncTask angelegt, den einem ThreadPoolExecutor hinzugefügt, der maximal 1 Task im Pool ausführt. Im onPreExecute des AsyncTasks dann x sekunden gewartet, in der doInBackground das Bild geholt und in der onPostExecute das Bild gesetzt.


    Nachdem ich das jetzt geschrieben hab, ist das vermutlich etwas zu Überdimensioniert mit Kanonen auf Spatzen geschossen ... hmm. Was anderes weiß ich grad nich, dass das schnufft. Wenn da mal 15 Buttons gemalt werden und ich kein bock mehr hab will ich die App ja auch sofort beenden und nicht warten, bis die Buttons endlich fertig sind, drück scho 5 mal auf meinen Home Button und bekomm dann ein "App reagiert nicht" von Android selbst.


    Gruß,
    matze

  • Die Idee mit dem AsyncTask finde ich tatsächlich gut.
    Allerdings brauchst du da nicht einen AsyncTask für jeden, sondern einer für alle sollte reichen.
    Je nachdem, wie man es implementiert...


    Den AsyncTask selbst brauchst du nur, um zu warten. Idealerweise um den Sound abzuspielen und so lange nichts zu tun, bis der Sound fertig ist.
    In der onPreExecute zeigst du den Button, in der onPostExecute versteckst du ihn wieder.


    Und je nach Runde hast rufst du den Task halt einmal, zweimal oder 75 mal hintereinander auf.
    Dann musst du dem Task nur noch mitteilen, welchen Button er vermurksen soll und gut ist.


    Zumindest fällt mir das spontan ein.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Folgender Timer müsste mir doch die Methoden buttons_ausgeben(zahlen[0]), buttons_ausgeben(zahlen[1]), usw im Abstand von 2 Sekunden aufrufen oder?
    Allerdings bricht meine App nach dem ersten Aufruf ab... -.-


    //Edit: Genauer gesagt bricht es ab sobald ein Zahlenwechsel im Array stattfindet. Sprich wenn in Array[0] bis Array[10] die gleiche Zahl steht funktioniert es, wenn aber dann in Array[11] eine andere steht geht nichts mehr...



    Java
    Timer timer = new Timer();
    	
    	  timer.scheduleAtFixedRate(new TimerTask() {
    		  private int i=0;
    		  public void run() {
    	    
    		   buttons_ausgeben(zahlen[i++]);
    		   
    	   }
    	  }, 0, 2000);


    In der Konsole funktioniert es. Wenn ich statt buttons_ausgeben... in der Konsole i ausgeben lasse, bekomme ich nacheinander 1,2,3,4,...


    Folgendes liefert das gleiche Ergebnis...


    Java
    TimerTask action = new TimerTask() {
            	private int i=0;
                public void run() {                                     
                    
                   buttons_ausgeben(zahlen[i++]);              
                }
            };
            
            Timer caretaker = new Timer();
            caretaker.schedule(action, 0, 2000);
  • Folgender Timer müsste mir doch die Methoden buttons_ausgeben(zahlen[0]), buttons_ausgeben(zahlen[1]), usw im Abstand von 2 Sekunden aufrufen oder?


    Keine Ahnung.
    Eigentlich nicht. Ich zumindest würde nicht davon ausgehen, dass immer dieselbe Instanz von TimerTask gefeuert wird.
    i als private static int zu definieren scheint mir sinnvoller – allerdings kann ich mich natürlich auch irren. :)


    Allerdings bricht meine App nach dem ersten Aufruf ab... -.-


    Da wäre wichtig zu wissen mit welcher Meldung sie abbricht.
    Vermutlich ein Scope Problem. Du willst auf zahlen zugreifen, doch da du dich ja in einer neuen (anonymen inneren) Klasse befindest, wird es zahlen nicht geben.


    Hier solltest du auf jeden Fall eine finale Variable erstellen, damit du darauf zugreifen kannst. Oder dir eine eigene Subklasse von TimerTask erstellen, der du dann das Array übergeben kannst.


    Mal Code für Möglichkeit 1:

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Genauer gesagt bricht es ab sobald ein Zahlenwechsel im Array stattfindet. Sprich wenn in Array[0] bis Array[10] die gleiche Zahl steht funktioniert es, wenn aber dann in Array[11] eine andere steht geht nichts mehr...



    Deine Lösung hat leider nicht funktioniert...



    Fehlermeldungen:



    06-28 15:18:35.460: W/dalvikvm(5040): threadid=11: thread exiting with uncaught exception (group=0x40a13300)
    06-28 15:18:35.468: E/AndroidRuntime(5040): FATAL EXCEPTION: Timer-0


    06-28 15:18:35.468: E/AndroidRuntime(5040): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.


    Wenn ich die Methoden einzeln aufrufe oder über eine einfache Schleife gibt es keine Probleme also an denen kann es nicht liegen. Dann leuchten alle Buttons natürlich nahezu zeitgleich ^^
    Nur wenn ich den Timer einbaue gibt es diese Probleme...

  • Ach sooo. Daran liegt das. ^^


    Tja, ein Timer startet halt auch einen Hintergrundthread. Der darf nicht einfach so an den Buttons rummalen.



    Irgendwie so halt.
    Also musst du das Anpassen der Buttons auf dem UI Thread machen und sonst nirgends.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

    Einmal editiert, zuletzt von Lucas de Vil ()

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!