【问题标题】:Android Program Hangs After Click点击后Android程序挂起
【发布时间】:2017-03-28 17:10:45
【问题描述】:

我正在编写一个安卓应用程序,通过多项选择来测试我的饮料食谱。按下选择后,应用程序会为正确答案着色并生成一个新问题。然而,经过几轮后,它挂起,我找不到原因。我在下面发布了代码和布局。

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;
}

}

这是布局文件

<?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>

logcat 开始挂起时会给出这个输出

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

我无法从我的代码中找出问题所在。这是当前应用程序中的唯一活动。谢谢。

更新: 我发现如果我删除 createAnswers 函数,它会停止挂起,但我还没有弄清楚它为什么会导致挂起。

已解决: 事实证明,由于岩石饮料没有混合器(混合器哈希图中的所有条目都是空字符串),它会影响 createAnswers 中的 else 语句,我在其中为混合器问题创建答案。我不知道为什么它会造成内存泄漏,但我删除了它,现在它可以正常工作了。

【问题讨论】:

  • 为什么需要 Handler?
  • 处理程序使屏幕暂停 3 秒,以便用户在更新到新问题之前可以看到正确答案。

标签: android freeze


【解决方案1】:

【讨论】:

  • 我尝试将处理程序设为静态并完全删除处理程序,但它仍然挂起。
  • 假设选项是固定大小的,你能否在声明它的顶部新建数组?choices = new String[4];在您的 createAnswers() 方法中看看这是否有所作为?您可以像这样在方法结束时清理数组:Arrays.fill(choices , 0);
  • 嘿切斯特,我发现了问题并在我的问题末尾写了它。感谢您的建议!
  • 以后没问题,把HashMaps中的所有问题、答案和数据保存在一个文件中或者使用developer.android.com/training/basics/data-storage/…
【解决方案2】:

您应该检查 createAnswers 函数中的 while 循环,它是每次都在可接受的时间结束还是需要很长时间,因为 count++ 处于可能无法满足的条件中

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多