2017-03-28 2 views
1

Ich schreibe eine Android-App, die mich auf Getränke Rezepte durch Multiple-Choice-Quiz prüft. Nachdem eine Auswahl getroffen wurde, färbt die App die richtige Antwort und erzeugt eine neue Frage. Nach einigen Runden hängt es jedoch und ich kann nicht finden warum. Ich habe den Code und das Layout unten veröffentlicht.Android-Programm hängt nach Klick

package com.example.frances.rocksdrinks; 

import android.graphics.Color; 
import android.os.Bundle; 
import android.os.Handler; 
import android.support.v7.app.AppCompatActivity; 
import android.view.View; 
import android.widget.TextView; 

import java.util.Arrays; 
import java.util.HashMap; 
import java.util.Map; 
import java.util.Random; 


public class Menu extends AppCompatActivity { 
String[] allDrinks = {"BOURBON ON THE ROCKS", "SCOTCH ON THE ROCKS", "TOP SHELF SCOTCH ON THE ROCKS", "BLACK RUSSIAN", "SICILIAN KISS", 
     "GOD MOTHER", "GOD FATHER", "RUSTY NAIL", "NUTTY IRISHMAN", "STINGER", "KAMIKAZE", "PURPLE HOOTER", "WINDEX", 
     "RASPBERRY KAMIKAZE", "MUDSLIDE", "AFTER FIVE", "B~51", "B~52", "B~53", "OATMEAL COOKIE"}; 

Map<String, String> liquor = new HashMap<String, String>() 
{{ 
    put("bourbon on the rocks", "1 1/2 oz Bourbon Whiskey"); 
    put("scotch on the rocks", "1 1/2 oz Scotch Whiskey"); 
    put("top shelf scotch on the rocks", "1 1/2 oz Scotch Whiskey"); 
    put("black russian", "1 1/4 oz Vodka & 3/4 oz Kahlua"); 
    put("sicilian kiss", "1 1/4 oz Southern Comfort & 3/4 oz Amaretto"); 
    put("god mother", "1 1/4 oz Vodka & 3/4 oz Amaretto"); 
    put("god father", "1 1/4 oz Scotch & 3/4 oz Amaretto"); 
    put("rusty nail", "1 1/4 oz Scotch & 3/4 oz Drambuie"); 
    put("Nutty Irishman", "1 1/4 oz Baileys & 3/4 oz Frangelico"); 
    put("stinger", "1 1/4 oz Brandy & 3/4 oz White Creme De Menthe"); 
    put("kamikaze", "1 1/4 oz Vodka & 3/4 oz Triple Sec"); 
    put("purple hooter", "1 1/4 oz Vodka & 3/4 oz Chambord"); 
    put("windex", "1 1/4 oz Vodka & 3/4 oz Blue Curacao"); 
    put("raspberry kamikaze", "1 1/4 oz Raspberry Vodka & 3/4 oz Triple Sec"); 
    put("mudslide", "1/2 oz Kahlua & 1/2 oz Baileys & 1/2 oz Vodka"); 
    put("after five", "1/2 oz Kahlua & 1/2 oz Baileys & 1/2 oz Peppermint Schnapps"); 
    put("b~51", "1/2 oz Kahlua & 1/2 oz Baileys & 1/2 oz Frangelico"); 
    put("b~52", "1/2 oz Kahlua & 1/2 oz Baileys & 1/2 oz Grand Marnier"); 
    put("b~53", "1/2 oz Kahlua & 1/2 oz Baileys & 1/2 oz Amaretto"); 
    put("oatmeal cookie", "1/2 oz Kahlua & 1/2 oz Baileys & 1/2 oz Goldschlager"); 
}}; 

Map<String, String> mixer = new HashMap<String, String>() 
{{ 
    put("bourbon on the rocks", ""); 
    put("scotch on the rocks", ""); 
    put("top shelf scotch on the rocks", ""); 
    put("black russian", ""); 
    put("sicilian kiss", ""); 
    put("god mother", ""); 
    put("god father", ""); 
    put("rusty nail", ""); 
    put("Nutty Irishman", ""); 
    put("stinger", ""); 
    put("kamikaze", ""); 
    put("purple hooter", ""); 
    put("windex", ""); 
    put("raspberry kamikaze", ""); 
    put("mudslide", ""); 
    put("after five", ""); 
    put("b~51", ""); 
    put("b~52", ""); 
    put("b~53", ""); 
    put("oatmeal cookie", ""); 
}}; 

Map<String, String> garnish = new HashMap<String, String>() 
{{ 
    put("bourbon on the rocks", "None"); 
    put("scotch on the rocks", "None"); 
    put("top shelf scotch on the rocks", "None"); 
    put("black russian", "None"); 
    put("sicilian kiss", "None"); 
    put("god mother", "None"); 
    put("god father", "None"); 
    put("rusty nail", "Lemon Twist"); 
    put("Nutty Irishman", "None"); 
    put("stinger", "Mint Leaf"); 
    put("kamikaze", "Splash Lime Juice"); 
    put("purple hooter", "Splash Lime Juice"); 
    put("windex", "Splash Lime Juice"); 
    put("raspberry kamikaze", "Splash Lime Juice"); 
    put("mudslide", "None"); 
    put("after five", "None"); 
    put("b~51", "None"); 
    put("b~52", "None"); 
    put("b~53", "None"); 
    put("oatmeal cookie", "None"); 
}}; 

Random r = new Random(); 

TextView choice1, choice2, choice3, choice4, answer, question; 
String ans; 
int qIndex; 
String[] choices; 
TextView correct; 
Handler handler; 

TextView pressed; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_menu); 

    choice1 = (TextView) findViewById(R.id.choice1); 
    choice2 = (TextView) findViewById(R.id.choice2); 
    choice3 = (TextView) findViewById(R.id.choice3); 
    choice4 = (TextView) findViewById(R.id.choice4); 

    answer = (TextView) findViewById(R.id.answer); 
    question = (TextView) findViewById(R.id.question); 

    handler = new Handler(); 

    createQuestion(); 
    createAnswers(); 

    question.setTextSize(21); 
} 

public void choice(View v) 
{ 
    pressed = (TextView) findViewById(v.getId()); 
    answer.setVisibility(View.VISIBLE); 

    if (pressed.getText().toString() == choices[0]) 
    { 
     pressed.setTextColor(Color.parseColor("#00BF00")); 
     answer.setText("CORRECT!"); 
     answer.setTextColor(Color.parseColor("#00BF00")); 
    } 
    else 
    { 
     pressed.setTextColor(Color.parseColor("#F60000")); 
     answer.setText("WRONG!"); 
     answer.setTextColor(Color.parseColor("#F60000")); 
     correct.setTextColor(Color.parseColor("#00BF00")); 
    } 

    handler.postDelayed(new Runnable() { 
     @Override 
     public void run() { 
      pressed.setTextColor(Color.parseColor("#777777")); 
      correct.setTextColor(Color.parseColor("#777777")); 
      answer.setVisibility(View.GONE); 

      createQuestion(); 
      createAnswers(); 
     } 
    }, 3000); 

} 

//if answer is a recipe, use 20sp as font size 
private void createQuestion() 
{ 
    String[] qs = {"Which drink contains ", "What garnish does drink contain", "What mixer does drink use", 
      "Which of the following describes a drink"}; 


    int i = r.nextInt(allDrinks.length); 
    ans = allDrinks[i]; 

    qIndex = r.nextInt(qs.length); 
    String q = ""; 

    if (qIndex != 0) 
    { 
     q = qs[qIndex].replace("drink", ans); 
    } 
    else 
    { 
     q = qs[qIndex] + liquor.get(ans.toLowerCase()); 

     if (!mixer.get(ans.toLowerCase()).isEmpty()) 
     { 
      q += " + " + mixer.get(ans.toLowerCase());; 
     } 

     if (!garnish.get(ans.toLowerCase()).equals("None")) 
     { 
      q += " + " + garnish.get(ans.toLowerCase()); 
     } 
    } 

    question.setText(q + "?"); 
} 

private void createAnswers() 
{ 
    choices = new String[4]; 
    int count = 1; 
    String a = ""; 

    if (qIndex == 3) 
    { 
     choices[0] = liquor.get(ans.toLowerCase()); 
     if (!mixer.get(ans.toLowerCase()).isEmpty()) 
     { 
      choices[0] += ", " + mixer.get(ans.toLowerCase()); 
     } 

     if (!garnish.get(ans.toLowerCase()).equals("None")) 
     { 
      choices[0] += ", " + garnish.get(ans.toLowerCase()); 
     } 

     while (count != 4) 
     { 
      int i = r.nextInt(allDrinks.length); 
      if (allDrinks[i] != ans) 
      { 
       a = liquor.get(allDrinks[i].toLowerCase()); 

       if (!mixer.get(ans.toLowerCase()).isEmpty()) 
       { 
        a += ", " + mixer.get(allDrinks[i].toLowerCase()); 
       } 

       if (!garnish.get(allDrinks[i].toLowerCase()).equals("None")) 
       { 
        a += ", " + garnish.get(allDrinks[i].toLowerCase()); 
       } 

       if (!Arrays.asList(choices).contains(a)) 
       { 
        choices[count] = a; 
        count++; 
       } 

      } 
     } 
    } 
    else if (qIndex == 0) 
    { 
     choices[0] = ans; 

     while (count != 4) 
     { 
      int i = r.nextInt(allDrinks.length); 
      if (allDrinks[i] != ans) 
      { 
       a = allDrinks[i]; 

       if (!Arrays.asList(choices).contains(a)) 
       { 
        choices[count] = a; 
        count++; 
       } 
      } 

     } 
    } 
    else if (qIndex == 1) 
    { 
     String[] g = {"Splash Coke", "Splash Grenadine", "Splash Sprite", "None"}; 
     choices[0] = garnish.get(ans.toLowerCase()); 

     while (count != 4) 
     { 
      int i = r.nextInt(g.length); 
      if (g[i] != choices[0]) 
      { 
       a = g[i]; 

       if (!Arrays.asList(choices).contains(a)) 
       { 
        choices[count] = a; 
        count++; 
       } 
      } 
     } 
    } 
    else 
    { 
     choices[0] = mixer.get(ans.toLowerCase()); 

     while (count != 4) 
     { 
      int i = r.nextInt(allDrinks.length); 
      if (mixer.get(allDrinks[i].toLowerCase()) != choices[0]) 
      { 
       a = mixer.get(allDrinks[i].toLowerCase()); 
       if (!Arrays.asList(choices).contains(a)) 
       { 
        choices[count] = a; 
        count++; 
       } 
      } 
     } 
    } 

    TextView[] cs = {choice1, choice2, choice3, choice4}; 
    cs = shuffle(cs); 
    correct = cs[0]; 

    for (int i = 0; i<4; i++) 
    { 
     if (qIndex == 3) 
     { 
      cs[i].setTextSize(12); 
     } 
     else 
     { 
      cs[i].setTextSize(18); 
     } 
     cs[i].setText(choices[i]); 
    } 
} 

private TextView[] shuffle(TextView[] arr) 
{ 
    int index; 
    TextView temp; 
    for (int i = arr.length - 1; i > 0; i--) 
    { 
     index = r.nextInt(i + 1); 
     temp = arr[index]; 
     arr[index] = arr[i]; 
     arr[i] = temp; 
    } 
    return arr; 
} 

}

Hier ist die Layout-Datei

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" android:layout_width="match_parent" 
android:layout_height="match_parent"> 

<TextView 
    android:id="@+id/question" 
    android:layout_width="wrap_content" 
    android:layout_height="140sp" 
    android:layout_gravity="center_horizontal" 
    android:layout_marginTop="20sp" 
    android:textSize="25sp" 
    android:layout_marginLeft="20sp" 
    android:layout_marginRight="20sp" 
    android:gravity="center" 
    android:textColor="@color/black" 
    android:text="Which drink contains 1/2 oz Jagermeister1/2 oz Peach Schnapps + Cranberry Juice"/> 

<RelativeLayout 
    android:layout_width="match_parent" 
    android:layout_height="300sp" 
    android:layout_marginTop="30sp"> 

    <TextView 
     android:id="@+id/choice1" 
     android:layout_marginLeft="0sp" 
     android:background="@drawable/shadowsmall" 
     android:layout_width="180sp" 
     android:layout_height="130sp" 
     android:text="Screwdriver" 
     android:textSize="23sp" 
     android:textColor="#777777" 
     android:clickable="true" 
     android:onClick="choice" 
     android:gravity="center"/> 

    <TextView 
     android:id="@+id/choice2" 
     android:layout_marginLeft="180sp" 
     android:background="@drawable/shadowsmall" 
     android:layout_width="180sp" 
     android:layout_height="130sp" 
     android:text="Screwdriver" 
     android:textSize="23sp" 
     android:textColor="#777777" 
     android:clickable="true" 
     android:onClick="choice" 
     android:gravity="center"/> 

    <TextView 
     android:id="@+id/choice3" 
     android:layout_marginTop="130sp" 
     android:layout_marginLeft="0sp" 
     android:background="@drawable/shadowsmall" 
     android:layout_width="180sp" 
     android:layout_height="130sp" 
     android:text="Screwdriver" 
     android:textSize="23sp" 
     android:textColor="#777777" 
     android:clickable="true" 
     android:onClick="choice" 
     android:gravity="center"/> 

    <TextView 
     android:id="@+id/choice4" 
     android:layout_marginTop="130sp" 
     android:layout_marginLeft="180sp" 
     android:background="@drawable/shadowsmall" 
     android:layout_width="180sp" 
     android:layout_height="130sp" 
     android:text="1 oz vodka, 50/50 orange and cranberry, lime" 
     android:textSize="23sp" 
     android:onClick="choice" 
     android:textColor="#777777" 
     android:clickable="true" 
     android:gravity="center"/> 

</RelativeLayout> 

<TextView 
    android:layout_marginTop="-40sp" 
    android:id="@+id/answer" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_gravity="center" 
    android:textSize="30sp" 
    android:textColor="@color/green" 
    android:textStyle="bold"/> 

</LinearLayout> 

Die logcat diesen Ausgang gibt, wenn es beginnt hängen

03-28 12:51:05.460 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 9.490ms 
03-28 12:51:15.605 29897-29913/com.example.frances.rocksdrinks I/art: Background sticky concurrent mark sweep GC freed 14222(509KB) AllocSpace objects, 0(0B) LOS objects, 24% free, 1825KB/2MB, paused 5.062ms total 11.585ms 
03-28 12:51:23.159 29897-29913/com.example.frances.rocksdrinks I/art: WaitForGcToComplete blocked for 10.660ms for cause Background 
03-28 12:52:48.768 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 6.314ms 
03-28 12:52:58.857 29897-29913/com.example.frances.rocksdrinks I/art: Background sticky concurrent mark sweep GC freed 30454(1094KB) AllocSpace objects, 0(0B) LOS objects, 38% free, 1708KB/2MB, paused 5.259ms total 13.447ms 
03-28 12:54:07.970 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 5.891ms 
03-28 12:54:24.523 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 5.254ms 
03-28 12:54:45.569 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 5.900ms 
03-28 12:54:49.078 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 8.536ms 
03-28 12:54:57.595 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 5.742ms 
03-28 12:55:30.525 29897-29912/com.example.frances.rocksdrinks I/art: WaitForGcToComplete blocked for 7.450ms for cause HeapTrim 
03-28 12:55:34.194 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 5.670ms 
03-28 12:55:56.904 29897-29913/com.example.frances.rocksdrinks W/art: Suspending all threads took: 5.412ms 
03-28 12:56:09.293 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 6.397ms 
03-28 12:56:37.481 29897-29913/com.example.frances.rocksdrinks I/art: Background sticky concurrent mark sweep GC freed 29570(1064KB) AllocSpace objects, 0(0B) LOS objects, 38% free, 1688KB/2MB, paused 10.745ms total 18.296ms 
03-28 12:56:42.810 29897-29913/com.example.frances.rocksdrinks W/art: Suspending all threads took: 6.896ms 
03-28 12:57:03.446 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 8.611ms 
03-28 12:57:10.750 29897-29912/com.example.frances.rocksdrinks I/art: WaitForGcToComplete blocked for 9.071ms for cause HeapTrim 
03-28 12:57:38.029 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 5.944ms 
03-28 12:57:45.548 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 5.624ms 
03-28 12:58:00.093 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 5.481ms 
03-28 12:58:10.900 29897-29912/com.example.frances.rocksdrinks I/art: WaitForGcToComplete blocked for 7.327ms for cause HeapTrim 
03-28 12:59:42.489 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 7.841ms 
03-28 13:00:01.148 29897-29912/com.example.frances.rocksdrinks I/art: WaitForGcToComplete blocked for 6.726ms for cause HeapTrim 
03-28 13:00:18.072 29897-29913/com.example.frances.rocksdrinks I/art: Background sticky concurrent mark sweep GC freed 26985(971KB) AllocSpace objects, 0(0B) LOS objects, 35% free, 1757KB/2MB, paused 6.471ms total 14.159ms 
03-28 13:00:21.155 29897-29912/com.example.frances.rocksdrinks I/art: WaitForGcToComplete blocked for 7.892ms for cause HeapTrim 
03-28 13:00:41.162 29897-29912/com.example.frances.rocksdrinks I/art: WaitForGcToComplete blocked for 5.154ms for cause HeapTrim 
03-28 13:02:48.702 29897-29908/com.example.frances.rocksdrinks W/art: Suspending all threads took: 5.836ms 
03-28 13:02:53.694 29897-29913/com.example.frances.rocksdrinks W/art: Suspending all threads took: 5.996ms 

Ich habe, um herauszufinden, nicht in der Lage gewesen, was falsch von meinem Code. Dies ist derzeit die einzige Aktivität in der App. Vielen Dank.

UPDATE: Ich fand, dass, wenn ich die CreateAnswers Funktion entferne, hört es auf zu hängen, aber ich habe nicht herausgefunden, warum es den Hang verursacht.

Gelöst: Stellt sich heraus, da Rocks Drinks keinen Mixer haben (alle Einträge im Mixer hashmap ist eine leere Zeichenfolge), wirkt sich auf die else-Anweisung in createAnswers, wo ich Antworten für die Mixer-Frage erstellen. Ich weiß nicht, warum es Speicherlecks verursachte, aber ich entfernte es und jetzt funktioniert es gut.

+0

Warum brauchen Sie einen Handler? –

+0

Der Handler ist so, dass der Bildschirm für 3 Sekunden pausiert, so dass der Benutzer die richtige Antwort sehen kann, bevor er auf eine neue Frage aktualisiert. –

Antwort

0

Machen Sie den Handler statische es verursacht Speicherlecks:

http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html

+0

Ich habe versucht, den Handler statisch zu machen und den Handler vollständig zu entfernen, aber es hängt immer noch. –

+0

Unter der Annahme, dass die Auswahl feste Größe ist, können Sie das Array oben neu erstellen, wo Sie es als Auswahl deklarieren = new String [4]; Suchen Sie in Ihren createAnswers() -Methoden nach, ob dies einen Unterschied macht? Sie können das Array am Ende der Methode wie folgt bereinigen: Arrays.fill (Auswahlmöglichkeiten, 0); –

+0

Hey Chester, ich fand das Problem und schrieb es am Ende meiner Frage. Danke für die Vorschläge! –

0

Sie sollten die while-Schleife in der createAnswers Funktion überprüfen, tut es jedes Mal zu akzeptablen Zeit endet oder dauert eine lange Zeit, weil Zählung ++ innen eine Bedingung, die nicht erfüllt werden kann