Anfängerproblem: Methode wird nicht nach Reihenfolge ausgeführt - Java Verständnisproblem

  • Antworten:8
  • OffenNicht stickyNicht beantwortet
  • Forum-Beiträge: 29

14.05.2017, 14:27:42 via Website

Hey, ich habe folgendes Problem:
in meinem Code wird eine Methode nicht nach Reihenfolge ausgeführt. Ich habe das Programmieren mit Python3 gelernt und bin deshalb daran gewöhnt, dass der Code Zeile für Zeile ausgeführt wird. Ist das bei Java anders?
Hier ist mein Code:

public void roundIntroduction(){
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            if (ordernumber == 1) {
                gameImages.setImageResource(R.drawable.number2);
                ordernumber++;

            }else{
                if (ordernumber == 2) {
                    gameImages.setImageResource(R.drawable.number1);
                    ordernumber++;
                }else{
                    if (ordernumber == 3) {
                        gameImages.setImageResource(R.drawable.go);
                        ordernumber = 1;
                        intruductionFinished = true;
                        Log.i("RelaxedActivity", "Roundintroduction finished");
                    }
                }
            }
            if(!intruductionFinished&&finished)roundIntroduction();
        }
    }, 1000);
}

public void newRound(){
    Log.i("RelaxedActivity", "Start new round");
    intruductionFinished = false;
    roundIntroduction();
    finished = false;
    intruductionFinished=false;
    gameImages.setImageResource(R.drawable.picture1);

}

Das ganze soll quasi einen Rundenbeginn in enem Spiel darstellen. In diesem soll am anfang ein Countdown runterlaufen (Metode roundIntroduction() ) und dann finished au false gesetzt werden und das Bild picture 1 angezeigt werden.
Wenn ich das ganze nun ausführe setzt das Programm aber als erstes finished auf false und zeigt das picture1 an und führt dann die Methode roundIntroduction() aus.
Wie aus dem obigen Code zu erkennen ist zerschießt das natürlich alles ... der Countdown läuft nicht durch, ect.

Kann mir jemand erklären, nach welcher Logik und Priorität Java Methoden ausführt?
Und hat jemand einen Tipp, wie ich dass Problem lösen kann ?
MfG ford.

Antworten
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.177

14.05.2017, 14:35:50 via Website

Hallo Ford,
solange du kein Multithreading benutzt, wird schon alles nach der Reihenfolge ausgeführt.
Wieso glaubst du dass es nicht so ist?

Tipp: Benutze den Debugger (schrittweises Debuggen) und Log ausgaben zum analysieren des Problems.
Zudem statt dem ganzen If gedöns würde ich an deiner Stelle einen switch/case benutzen.
Bleibt übersichtlicher..

Und bist du sicher dass die Bedingung richtig ist: if(!intruductionFinished&&finished)roundIntroduction();
wo liegt der unterschied zwischen "intruductionFinished" und "finished"?
Der Timer wird nur komplett durchlaufen wenn "intruductionFinished"=false und "finished" = true

LG Pascal //It's not a bug, it's a feature. :) ;)

Ford Prefect

Antworten
  • Forum-Beiträge: 29

14.05.2017, 14:49:32 via Website

Multithreding benutze ich nicht, zu mindest nicht bewust :)
Das mit finished und introduction finished ist schon richtig. finished bezieht sich auf die ganze Runde (Taucht in meinem Code noch ein paar mal auf) und introductionFinished nur in dem Countdown.

Ich glaube dass es nicht so ist, weil ich den ImageView mit einem onClickListener versehen habe, der aber nur dann eine Aktion ausführt wenn finished false ist.

 public void onClick(View v) {
    if (!finished){
        playSound();
        counter++;
        actualizeScreen();
    }
}

Während roundIntroduction() passiert aber trotzdem was wenn ich klicke. Außerdem läuft roundIntroduction() nicht durch sonder bleibt bei dem ersten Bild stehen. Das heißt für mich, dass eine der Bedingungen von

if(!intruductionFinished&&finished)roundIntroduction();

nicht zutrifft. Ich erkläre finished aber von Anfang an als true und es wird dann erst von newRound() auf false gesetzt.

Danke für den Tipp mit switch case. Ist wirklich viel übersichtlicher :)

Ps.: Vielen Dank für deine Hilfe. Ich bin ziemlich frisch in der Android Programmierung und habe in diesem Forum schon so viel gelernt... :)

Antworten
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.177

14.05.2017, 14:57:37 via Website

Mach dir an diese stelle mal ausgaben mit Log.d(..);
Am besten jede der beiden boolean Variablen und danach die verknüpfung beider.
Dann weißt du ziemlich schnell woran es liegt

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
  • Forum-Beiträge: 29

14.05.2017, 15:12:40 via Website

Also ich weis jetzt mit Sicherheit, dass er roundIntroduction() als letztes ausführt. Ich habe meine Log.d() befehle wie folgt gesetzt :

public void roundIntroduction(){
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            if (ordernumber == 1) {
                gameImages.setImageResource(R.drawable.number2);
                ordernumber++;
                Log.d("RelaxedActivity", "roundIntroduction started");

            }else{
                if (ordernumber == 2) {
                    gameImages.setImageResource(R.drawable.number1);
                    ordernumber++;
                }else{
                    if (ordernumber == 3) {
                        gameImages.setImageResource(R.drawable.go);
                        ordernumber = 1;
                        intruductionFinished = true;
                        Log.i("RelaxedActivity", "Roundintroduction finished");
                    }
                }
            }
            if(!intruductionFinished&&finished){
                roundIntroduction();
                Log.d("RelaxedActivity", "roundIntroduction get's repeated");
            }

        }
    }, 1000);
}

public void newRound(){
    Log.i("RelaxedActivity", "Start new round");
    intruductionFinished = false;
    Log.d("RelaxedActivity", "introductionFinished = false");
    roundIntroduction();
    finished = false;
    Log.d("RelaxedActivity", "finished = false");
    gameImages.setImageResource(R.drawable.picture1);
    Log.d("RelaxedActivity", "Picture1 set");

}

und das sind meien Log files:

05-14 15:07:02.859 7551-7551/slartbart.example I/RelaxedActivity: onCreate finished
05-14 15:07:02.859 7551-7551/slartbart.example I/RelaxedActivity: Start new round
05-14 15:07:02.859 7551-7551/slartbart.example D/RelaxedActivity: introductionFinished = false
05-14 15:07:02.860 7551-7551/slartbart.example D/RelaxedActivity: finished = false
05-14 15:07:02.916 7551-7558/slartbart.example W/art: Suspending all threads took: 17.610ms
05-14 15:07:02.944 7551-7562/slartbart.example I/art: Background sticky concurrent mark sweep GC freed 1075(126KB) AllocSpace objects, 0(0B) LOS objects, 0% free, 44MB/44MB, paused 14.473ms total 69.485ms
05-14 15:07:02.953 7551-7551/slartbart.example D/RelaxedActivity: Picture1 set
05-14 15:07:03.069 7551-7562/slartbart.example I/art: Background partial concurrent mark sweep GC freed 388(22KB) AllocSpace objects, 0(0B) LOS objects, 8% free, 44MB/48MB, paused 3.199ms total 102.446ms
05-14 15:07:03.107 7551-7586/slartbart.example E/EGL_emulation: tid 7586: eglSurfaceAttrib(1174): error 0x3009 (EGL_BAD_MATCH)
05-14 15:07:03.107 7551-7586/slartbart.example W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0x9ca6fc80, error=EGL_BAD_MATCH
05-14 15:07:03.935 7551-7551/slartbart.example D/RelaxedActivity: roundIntroduction started+

danach ist Schluss.
Ich weis gerade wirklich nicht weiter :)

— geändert am 14.05.2017, 15:14:06

Antworten
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.177

14.05.2017, 15:20:03 via Website

Hehe, ich nehme an die Rektusion funktioniert nicht..

Mit meiner ausgabe meine ich sowas, mach das bitte mal:

Log.d("Status",String.format("intruductionFinished: %s , finished: %s
, !intruductionFinished&&finished:
%s",String.valueOf(intruductionFinished),String.valueOf(finished),String.valueOf(!intruductionFinished&&finished)));

Und das bitte vor die if im Runnable.

Edit: Und bitte mit SWITCH, ich kann diese ifs so nicht mehr sehen :O

— geändert am 14.05.2017, 15:20:40

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
  • Forum-Beiträge: 29

14.05.2017, 16:11:07 via Website

ok ich hab es jetzt so gemacht:

public void roundIntroduction(){
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            switch (ordernumber){
                case 1:
                    gameImages.setImageResource(R.drawable.number2);
                    ordernumber++;
                    Log.d("RelaxedActivity", "roundIntroduction started");
                    break;

                case 2:
                    gameImages.setImageResource(R.drawable.number1);
                    ordernumber++;
                    break;

                case 3:
                    gameImages.setImageResource(R.drawable.go);
                    ordernumber = 1;
                    intruductionFinished = true;
                    Log.i("RelaxedActivity", "Roundintroduction finished");
                    break;
            }
            Log.d("Status",String.format("intruductionFinished: %s , finished: %s, !intruductionFinished&&finished: %s",String.valueOf(intruductionFinished),String.valueOf(finished),String.valueOf(!intruductionFinished&&finished)));
            if(!intruductionFinished&&finished){
                roundIntroduction();

            }

        }
    }, 1000);
}

und er gibt mir aus :

05-14 16:03:02.323 6738-6738/slartbart.example I/RelaxedActivity: onCreate finished
05-14 16:03:02.323 6738-6738/slartbart.example I/RelaxedActivity: Start new round
05-14 16:03:02.323 6738-6738/slartbart.example D/RelaxedActivity: introductionFinished = false
05-14 16:03:02.326 6738-6738/slartbart.example D/RelaxedActivity: finished = false
05-14 16:03:02.396 6738-6738/slartbart.example D/RelaxedActivity: Picture1 set
05-14 16:03:02.410 6738-6749/slartbart.example I/art: Background sticky concurrent mark sweep GC freed 1134(129KB) AllocSpace objects, 0(0B) LOS objects, 0% free, 44MB/44MB, paused 10.369ms total 70.105ms
05-14 16:03:02.553 6738-6783/slartbart.example E/EGL_emulation: tid 6783: eglSurfaceAttrib(1174): error 0x3009 (EGL_BAD_MATCH)
05-14 16:03:02.553 6738-6783/slartbart.example W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xa8d5c340, error=EGL_BAD_MATCH
05-14 16:03:03.431 6738-6738/slartbart.example D/RelaxedActivity: roundIntroduction started
05-14 16:03:03.432 6738-6738/slartbart.example D/Status: intruductionFinished: false , finished: false, !intruductionFinished&&finished: false

Das heißt doch, dass finished false ist, wenn er roundIntroduction() startet, oder ?
Dass kann aber eig. nicht sein, da ich finished als true initialisiert habe...

Antworten
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.177

14.05.2017, 18:25:31 via Website

Damit hast du ja schonmal den Fehler :)-
Na ja ich nehme an du nutzt newRound auch für die Startrunde oder?

Dann schau mal was hier steht:

intruductionFinished = false;
Log.d("RelaxedActivity", "introductionFinished = false");
roundIntroduction();
finished = false;

Du musst immer aufpassen wo du die Varablen setzt.
Außerdem wenn man eine Varable Finished nennt, ist diese True wenn das Spiel beendet ist, somit muss die laut Logik false sein wenn es laufen soll. Vielleicht solltest du deine Bedingung einfach anpassen.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
  • Forum-Beiträge: 29

14.05.2017, 22:58:59 via Website

Das hat leider auch nicht funktioniert.
Ich habe das Problem jetzt mit einer AnimationDrawable gelöst.
jetzt sieht das ganze so aus:

public void roundIntroduction(){
    gameImages.setBackgroundResource(R.drawable.animation_list_round_introduction);
    roundIntroductionAnimation = (AnimationDrawable) gameImages.getBackground();
    roundIntroductionAnimation.start();

}

public void newRound(){
    Log.i("RelaxedActivity", "Start new round");
    finished = true;
    gameImages.setImageResource(R.drawable.empty);
    roundIntroduction();
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            finished = false;
            gameImages.setImageResource(R.drawable.picture1);
        }
    }, 5500);
}

und die dazugehörige animation_list:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<item android:drawable="@drawable/number3" android:duration="1500"/>
<item android:drawable="@drawable/number2" android:duration="1500"/>
<item android:drawable="@drawable/number1" android:duration="1500"/>
<item android:drawable="@drawable/go" android:duration="1000"/>
<item android:drawable="@drawable/empty" android:duration="1"/>

Dadurch ist jetzt nur ein neues Problem aufgetreten:
Er spielt die Animation nur beim ersten mal aufrufen von roundIntroduction() ab.
Ich glaube das liegt an dem

android:oneshot="true"

in der xml datei.
weiß jemand wie ich das so einstellen kann, dass er die Animation jedes mal abspielt, aber nicht looped, sondern eben nur ein mal durchgeht ?

Antworten

Empfohlene Artikel