0

I got a weird problem with my method that's creating dialoges with questions. Basically what I've done is creating a hashmap table with questions and a identifier, which I'm using for my if-statements on the positive -and negative buttons of the dialog window.

Here's the program code:

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

PROBLEM: First of all it seems to loop through the hashmap in a weird order. It's starting with "Have you not cut the power?" and therefor skipping the first question. The main problem when I run the program is that the application crash after I've answered the 2:nd dialog popup. Basically it runs through 1 question perfectly but when I'm answering the 2:nd question it krasches, no matter what button I reply with.

Here's the errors:

04-26 14:13:35.163: E/AndroidRuntime(7953): FATAL EXCEPTION: main
04-26 14:13:35.163: E/AndroidRuntime(7953): java.lang.NullPointerException
04-26 14:13:35.163: E/AndroidRuntime(7953):     at   com.example.ovakoappen.QuestionsActivity$2.onClick(QuestionsActivity.java:85)
04-26 14:13:35.163: E/AndroidRuntime(7953):     at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:185)
04-26 14:13:35.163: E/AndroidRuntime(7953):     at android.os.Handler.dispatchMessage(Handler.java:99)
04-26 14:13:35.163: E/AndroidRuntime(7953):     at android.os.Looper.loop(Looper.java:137)
04-26 14:13:35.163: E/AndroidRuntime(7953):     at android.app.ActivityThread.main(ActivityThread.java:5279)
04-26 14:13:35.163: E/AndroidRuntime(7953):     at java.lang.reflect.Method.invokeNative(Native Method)
04-26 14:13:35.163: E/AndroidRuntime(7953):     at java.lang.reflect.Method.invoke(Method.java:511)
04-26 14:13:35.163: E/AndroidRuntime(7953):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
04-26 14:13:35.163: E/AndroidRuntime(7953):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
04-26 14:13:35.163: E/AndroidRuntime(7953):     at dalvik.system.NativeStart.main(Native Method)
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
user3572555
  • 71
  • 1
  • 6

4 Answers4

0

About the first "problem" with the order: A hash map does not guarantee a specific order. More presicely the order doesn't even have to be constant over the time. You would have to use something else instead.

nils
  • 1,362
  • 1
  • 8
  • 15
  • Ah okay thx! I was using an arraylist before but I wanted to be able to put the "identifier" and then seperate it from the question. Hence why i choosed hash map. But I think I would want the questions to be shown in a specific order. – user3572555 Apr 26 '14 at 12:33
  • well, looking at the Java API (which is somehow very related to the Android Java API), I would take a look at classes which implement the SortedMap interface. This should solve your problem: http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html – nils Apr 26 '14 at 12:36
0

For your order problem, you can see use a LinkedHashMap which will get you items in the insertion order (source)

For the crash you encounter, it is because all dialogs are created at once in the onCreate method of your activity and once you validate a dialog, your variable identifier becomes null. You should only create one dialog at a time and create the following in the dismissListener of your dialog. Details about dismiss listeners here.

Community
  • 1
  • 1
TheCopycat
  • 401
  • 2
  • 6
0

There is a logical error in the code:

you create N dialogs (here, at least 4) in a loop. Yet each of the dialogs utilizes the same question/identifier variables.

Meaning: the 1st one will change identifier value after it exits, and this value will use 2nd dialog. Dialogs in Android are non-blocking. When you show a dialog, the execution of create_dialog_method() ends and the for-loop is running! Even if you have dialog still visible, another one will be created on top of it.

In effect you have 4 dialogs created one by one, all shown but one visible.

Then in an onClick() method you set identifier to null. This is the value that the 2nd dialog will see and this is why it crashes.

There are at least 2 solutions:

  1. Create only one dialog at a time, and create new one after you close it with yes/no button or on a dismiss listener.
  2. Create your own dialog class and pass question/identifier there -- so they are independent from your main question map.
Marcin Gil
  • 68,043
  • 8
  • 59
  • 60
  • Ah okay, thx for the explanation! That's how i want my solution to be(creating one dialog at a time).I'm still unsure how to get there code-wise though. – user3572555 Apr 26 '14 at 13:03
0
  1. For the ordering problem: you could use LinkedHashMap to ensure the ordering.

  2. The NullPointerException is the result of calling method equalsIgnoreCase on null object, you set identifier to null in the first iteration: you should make question and identifier method parameters rather than fields.

here is the code after change:

    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() {}
    }
Aboalnaga
  • 602
  • 6
  • 16
  • 1
    Thanks that solved my problem! I just had to make a small adjustment by swapping place with the method call and Toast under the NO button. – user3572555 Apr 26 '14 at 14:56
  • @user Sorry I didn't notice that, I've fixed the answer to reflect the proper logic – Aboalnaga Apr 26 '14 at 15:19