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.
Warum brauchen Sie einen Handler? –
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. –