Java 当第二个对话框窗口被应答时,我的应用程序崩溃

Java 当第二个对话框窗口被应答时,我的应用程序崩溃,java,android,nullpointerexception,Java,Android,Nullpointerexception,我的方法有一个奇怪的问题,那就是创建带有问题的对话。基本上,我所做的是创建一个包含问题和标识符的hashmap表,用于对话框窗口的正负按钮上的if语句 以下是程序代码: public class QuestionsActivity extends Activity { String question = null; String identifier = null; @Override public void onCreate(Bundle savedInstanceState) { s

我的方法有一个奇怪的问题,那就是创建带有问题的对话。基本上,我所做的是创建一个包含问题和标识符的hashmap表,用于对话框窗口的正负按钮上的if语句

以下是程序代码:

public class QuestionsActivity extends Activity {
String question = null;
String identifier = null;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test_layout);


    // 0 = call showRiskEvaluationDialog() on button NO.  1 = call showRiskEvaluationDialog(); on button YES
    Map<String, String> question_map = new HashMap<String, String>();
    question_map.put("Have you cut the power?", "0");
    question_map.put("Have you not cut the power?", "1");
    question_map.put("Do you know your work assignment?", "0");
    question_map.put("Don't you know your work assignment?", "1");

    //For loop to extract a question and identifier from the hashmap
    for(Entry<String, String> entry : question_map.entrySet()) 
    {
        question = entry.getKey();
        identifier = entry.getValue();

        create_dialog_method(question);
    }

}

/**
 * Method to create a dialogbox with a question and YES, NO buttons
 * @param question_param
 */
public void create_dialog_method(String question_param) {
    AlertDialog.Builder alert = new AlertDialog.Builder(this);

    alert.setTitle("Titel");
    alert.setMessage(question_param);

    alert.setPositiveButton("YES", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {

            if (identifier.equalsIgnoreCase("1")) {

                showRiskEvaluationDialog();

                identifier = null;
            } else if (identifier.equalsIgnoreCase("0")) {

                Toast.makeText(getApplicationContext(), "Saved",
                       Toast.LENGTH_SHORT).show();

                identifier = null;

            }

        }
    });

    alert.setNegativeButton("NO", new DialogInterface.OnClickListener(){
        public void onClick(DialogInterface dialog, int whichButton) {

            if (identifier.equalsIgnoreCase("0")) {

                showRiskEvaluationDialog();

                identifier = null;

            } else if (identifier.equalsIgnoreCase("1")) {

                Toast.makeText(getApplicationContext(), "Saved",
                           Toast.LENGTH_SHORT).show();

                identifier = null;
            }

        }
    });

    alert.show();
}

关于顺序的第一个“问题”:哈希映射不能保证特定的顺序。更具预见性的是,顺序甚至不必随着时间的推移而保持不变。您将不得不使用其他工具。

对于您的订单问题,您可以看到使用
LinkedHashMap
,它将按插入顺序获取项目()


对于您遇到的崩溃,这是因为所有对话框都是在活动的
onCreate
方法中一次创建的,并且一旦您验证了一个对话框,您的变量
identifier
将变为null。一次只能创建一个对话框,并在对话框的dismissListener中创建以下内容。有关解除侦听器的详细信息。

代码中存在逻辑错误:

在循环中创建N个对话框(这里至少4个)。然而,每个对话框都使用相同的
问题
/
标识符
变量

含义:第一个将在退出后更改
标识符
值,该值将使用第二个对话框。Android中的对话框是非阻塞的。显示对话框时,
create\u dialog\u method()
的执行结束,for循环正在运行!即使对话框仍然可见,也会在其顶部创建另一个对话框

实际上,您已经一个接一个地创建了4个对话框,所有对话框都显示出来,只有一个是可见的

然后在
onClick()
方法中将
identifier
设置为null。这是第二个对话框将看到的值,这就是它崩溃的原因

至少有两种解决方案:

  • 一次只创建一个对话框,并在使用“是/否”按钮或关闭侦听器后创建新的对话框
  • 创建您自己的对话类并在其中传递问题/标识符——这样它们就独立于您的主要问题映射
  • 对于订购问题:您可以使用来确保订购

  • NullPointerException
    是调用null对象上的方法
    equalsIgnoreCase
    的结果,您在第一次迭代中将
    identifier
    设置为
    null
    :您应该生成
    question
    identifier
    方法参数,而不是字段

  • 以下是更改后的代码:

        public class QuestionsActivity extends Activity {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.test_layout);
    
           // false = call showRiskEvaluationDialog() on button NO
           // true  = call showRiskEvaluationDialog() on button YES
           Map<String, Boolean> question_map = new LinkedHashMap<String, Boolean>();
           question_map.put("Have you cut the power?", false);
           question_map.put("Have you not cut the power?", true);
           question_map.put("Do you know your work assignment?", false);
           question_map.put("Don't you know your work assignment?", true);
    
           // For loop to extract a question and identifier from the Map
           for (Entry<String, Boolean> entry : question_map.entrySet()){
              create_dialog_method(entry.getKey(), entry.getValue());
           }
        }
    
        /**
         * Method to create a dialogbox with a question and YES, NO buttons
         *
         * @param question_param
         * @param identifier
         */
        public void create_dialog_method(String question_param, final boolean identifier) {
           AlertDialog.Builder alert = new AlertDialog.Builder(this);
    
           alert.setTitle("Title");
           alert.setMessage(question_param);
    
           alert.setPositiveButton("YES", new DialogInterface.OnClickListener() {
              @Override
              public void onClick(DialogInterface dialog, int whichButton) {
    
                 if (identifier)
                    showRiskEvaluationDialog();
                 else
                    Toast.makeText(getApplicationContext(), "Saved",
                          Toast.LENGTH_SHORT).show();
              }
           });
    
           alert.setNegativeButton("NO", new DialogInterface.OnClickListener() {
              @Override
              public void onClick(DialogInterface dialog, int whichButton) {
    
                 if (identifier)
                    Toast.makeText(getApplicationContext(), "Saved",
                          Toast.LENGTH_SHORT).show();
                 else
                    showRiskEvaluationDialog();
              }
           });
           alert.show();
        }
    
        private void showRiskEvaluationDialog() {}
        }
    
    公共类问题活动扩展活动{
    @凌驾
    创建时的公共void(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test_布局);
    //false=在按钮NO上调用showRiskEvaluationDialog()
    //true=在按钮YES上调用showRiskEvaluationDialog()
    映射问题_Map=新建LinkedHashMap();
    问题(你切断电源了吗?(错));
    问题(你没有切断电源吗?(对));
    问题(你知道你的工作任务吗?错);;
    问题(你不知道你的工作任务吗?),正确);
    //For循环从地图中提取问题和标识符
    for(条目:问题\映射.entrySet()){
    创建对话框方法(entry.getKey(),entry.getValue());
    }
    }
    /**
    *方法创建带有问题和是、否按钮的对话框
    *
    *@param-question\u-param
    *@param标识符
    */
    公共void创建对话框方法(字符串问题参数,最终布尔标识符){
    AlertDialog.Builder alert=新建AlertDialog.Builder(此);
    警报。设置标题(“标题”);
    警报。设置消息(问题参数);
    alert.setPositiveButton(“是”,新的DialogInterface.OnClickListener(){
    @凌驾
    public void onClick(对话框接口对话框,int whichButton){
    if(标识符)
    showRiskEvaluationDialog();
    其他的
    Toast.makeText(getApplicationContext(),“已保存”,
    吐司。长度(短)。show();
    }
    });
    alert.setNegativeButton(“否”,新的DialogInterface.OnClickListener(){
    @凌驾
    public void onClick(对话框接口对话框,int whichButton){
    if(标识符)
    Toast.makeText(getApplicationContext(),“已保存”,
    吐司。长度(短)。show();
    其他的
    showRiskEvaluationDialog();
    }
    });
    alert.show();
    }
    私有void showRiskEvaluationDialog(){}
    }
    
    啊,好的,谢谢!我以前使用过arraylist,但我希望能够放置“标识符”,然后将其与问题分开。因此我选择了哈希映射。但是我想我希望问题以特定的顺序显示出来。好吧,看看Java API(它与Android Java API有很大的关联),我想看看实现SortedMap接口的类。这应该可以解决你的问题:啊,好吧,谢谢你的解释!这就是我想要的解决方案(一次创建一个对话框)。但我仍然不确定如何在代码方面达到目的。谢谢,这解决了我的问题!我只需要通过在“否”按钮下用方法调用和Toast替换位置来进行一个小的调整。@用户抱歉,我没有注意到,我已经修改了答案以反映正确的逻辑
        public class QuestionsActivity extends Activity {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.test_layout);
    
           // false = call showRiskEvaluationDialog() on button NO
           // true  = call showRiskEvaluationDialog() on button YES
           Map<String, Boolean> question_map = new LinkedHashMap<String, Boolean>();
           question_map.put("Have you cut the power?", false);
           question_map.put("Have you not cut the power?", true);
           question_map.put("Do you know your work assignment?", false);
           question_map.put("Don't you know your work assignment?", true);
    
           // For loop to extract a question and identifier from the Map
           for (Entry<String, Boolean> entry : question_map.entrySet()){
              create_dialog_method(entry.getKey(), entry.getValue());
           }
        }
    
        /**
         * Method to create a dialogbox with a question and YES, NO buttons
         *
         * @param question_param
         * @param identifier
         */
        public void create_dialog_method(String question_param, final boolean identifier) {
           AlertDialog.Builder alert = new AlertDialog.Builder(this);
    
           alert.setTitle("Title");
           alert.setMessage(question_param);
    
           alert.setPositiveButton("YES", new DialogInterface.OnClickListener() {
              @Override
              public void onClick(DialogInterface dialog, int whichButton) {
    
                 if (identifier)
                    showRiskEvaluationDialog();
                 else
                    Toast.makeText(getApplicationContext(), "Saved",
                          Toast.LENGTH_SHORT).show();
              }
           });
    
           alert.setNegativeButton("NO", new DialogInterface.OnClickListener() {
              @Override
              public void onClick(DialogInterface dialog, int whichButton) {
    
                 if (identifier)
                    Toast.makeText(getApplicationContext(), "Saved",
                          Toast.LENGTH_SHORT).show();
                 else
                    showRiskEvaluationDialog();
              }
           });
           alert.show();
        }
    
        private void showRiskEvaluationDialog() {}
        }