简体   繁体   中英

Android Form Validation - How do I prevent a null field from crashing my application on button press?

I have a form which lets the user add entries into a raffle. However if the user leaves one of these fields blank and presses the submit button the app crashes. I tried to get around this by creating an if statement - if any of the fields are null, do nothing. Else, run the intent. However this still does not fix my problem. Pressing the button still causes a crash.

Here is my code:

 public void addEntrySubmitButtonClick(View view) {


        Intent addEntryIntent = getIntent();
        int currentRaffleID = addEntryIntent.getIntExtra("raffleIndexInList", 0);
        Raffle currentRaffle = Raffle.raffleArrayList.get(currentRaffleID);
        String newEntryForename = String.valueOf(addEntryForename.getText());
        String newEntrySurname = String.valueOf(addEntrySurname.getText());
        int newEntryTelephoneNo = Integer.parseInt(String.valueOf(addEntryTelephoneNo.getText()));
        int newEntryTicketCount = Integer.parseInt(String.valueOf(addEntryTicketCount.getText()));
        int newEntryRaffleId = currentRaffle.getId();

        if ((newEntryForename.equals(null)) || (newEntrySurname.equals(null)) || (String.valueOf(addEntryTelephoneNo).equals(null)) || (String.valueOf(addEntryTicketCount).equals(null))){
        Intent failIntent = new Intent();
        } else {
            Entry newEntry = new Entry(newEntryForename, newEntrySurname, newEntryTelephoneNo, newEntryTicketCount, newEntryRaffleId);


            // Get the list of raffles
            for(Raffle currentEntryRaffle : Raffle.raffleArrayList) {
                if((currentEntryRaffle.getId() == newEntryRaffleId) && ((currentEntryRaffle.getEntryArrayList().size()) < (currentEntryRaffle.getMaxTickets()))) {
                    int counter=0;
                    do {
                        currentEntryRaffle.getEntryArrayList().add(newEntry);
                        counter++;
                    } while(counter < newEntryTicketCount);
                }
            }

            Intent returnIntent = new Intent();
            setResult(RESULT_CANCELED, returnIntent);
            finish();
        }

Here is the logcat:

10-24 10:48:42.599  19481-19481/com.example.rafflemanager E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.IllegalStateException: Could not execute method of the activity
            at android.view.View$1.onClick(View.java:3628)
            at android.view.View.performClick(View.java:4128)
            at android.view.View$PerformClick.run(View.java:17142)
            at android.os.Handler.handleCallback(Handler.java:615)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:213)
            at android.app.ActivityThread.main(ActivityThread.java:4787)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:809)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:576)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.reflect.InvocationTargetException
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at android.view.View$1.onClick(View.java:3623)
            at android.view.View.performClick(View.java:4128)
            at android.view.View$PerformClick.run(View.java:17142)
            at android.os.Handler.handleCallback(Handler.java:615)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:213)
            at android.app.ActivityThread.main(ActivityThread.java:4787)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:809)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:576)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NumberFormatException: Invalid int: ""
            at java.lang.Integer.invalidInt(Integer.java:138)
            at java.lang.Integer.parseInt(Integer.java:359)
            at java.lang.Integer.parseInt(Integer.java:332)
            at com.example.rafflemanager.AddEntry.addEntrySubmitButtonClick(AddEntry.java:48)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at android.view.View$1.onClick(View.java:3623)
            at android.view.View.performClick(View.java:4128)
            at android.view.View$PerformClick.run(View.java:17142)
            at android.os.Handler.handleCallback(Handler.java:615)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:213)
            at android.app.ActivityThread.main(ActivityThread.java:4787)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:809)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:576)
            at dalvik.system.NativeStart.main(Native Method)
newEntryForename.equals(null)

The above expression will either evaluate to false or throw a NullPointerException . It is impossible to call a method on a null reference.

String.valueOf(addEntryTelephoneNo).equals(null)

The above expression will always evaluate to false . From String.valueOf javadoc:

Returns: if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.

What you want instead is simply

addEntryTelephoneNo == null

and similar for other cases.

Furthermore note that you are trying to parse the value before you have null-checked it:

int newEntryTelephoneNo = Integer.parseInt(String.valueOf(addEntryTelephoneNo.getText()));

Move that code to after the null check.

I'm writing this from a smartphone so I won't include any codesamples with this answer.

Anyway... First of all remove all String.valueOf() calls - they are redundant. Second, to see if a value is null, check for value == null, not value.equals(null). If value is null, it doesn't have the method equals(), and will thus lead to a NullReferenceException.

Also, don't call Integer.parseInt(value) before you have made sure that value isn't null.

Disabling the send button when the EditText is empty when using imeOption= actionSend

message.addTextChangedListener(new TextWatcher() {

public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {}

public void afterTextChanged(Editable s) {
    if (s == null || s.length() == 0) {
       send.setEnabled(false);
       message.setImeOptions(EditorInfo.IME_FLAG_NO_ENTER_ACTION);
    }
    else {
      send.setEnabled(true);
      message.setImeOptions( /* whatever you previously had */ );
    }

}

To check if a string is empty (null or length 0) use TextUtils.isEmpty() . Here's an example:

int newEntryTelephoneNo;
if (TextUtils.isEmpty(addEntryTelephoneNo.getText())) {
    newEntryTelephoneNo = 0;
} else {
    newEntryTelephoneNo = Integer.parseInt(addEntryTelephoneNo.getText());
}

The problem in your logcat is this :

Caused by: java.lang.NumberFormatException: Invalid int: ""

Without line numbers, I deduct that the problem comes from one line like this one :

int newEntryTelephoneNo = Integer.parseInt(String.valueOf(addEntryTelephoneNo.getText()));

Reading the following docs give us a hint : http://developer.android.com/reference/java/lang/Integer.html#parseInt(java.lang.String)

Throws

NumberFormatException if string cannot be parsed as an integer value.

The Integer.parseInt() seems not able to parse an empty String to an int (and it's normal, because a int can't be null ).

So I think you should make something like that :

int newEntryTelephoneNo = 0;
if (!TextUtils.isEmpty(addEntryTelephoneNo.getText())) {
    newEntryTelephoneNo = Integer.parseInt(addEntryTelephoneNo.getText());
}

Not about the main question

Also, as other answers and comment said, you have to use this to check the "nullity" of an object :

myObject == null

instead of

myObject.equals(null)

because you can't even call equals() or any other methods on a null instance.

The logcat clearly shows the exception occurs when the call to Integer.parseInt throws a NumberFormatException . This occurs when the string cannot be converted to an int. If you check the line numbers you will see exactly which conversion generated the exception.

Depending on your needs you probably want to both test for acceptable invalid entries like empty string and catch NumberFormatException due to invalid input so that you can inform the user of the invalid entry.

Here is the code you need:

public void addEntrySubmitButtonClick(View view) {


    Intent addEntryIntent = getIntent();
    int currentRaffleID = addEntryIntent.getIntExtra("raffleIndexInList", 0);
    Raffle currentRaffle = Raffle.raffleArrayList.get(currentRaffleID);
    String newEntryForename = String.valueOf(addEntryForename.getText());
    String newEntrySurname = String.valueOf(addEntrySurname.getText());
    int newEntryTelephoneNo = Integer.parseInt(String.valueOf(addEntryTelephoneNo.getText()));
    int newEntryTicketCount = Integer.parseInt(String.valueOf(addEntryTicketCount.getText()));
    int newEntryRaffleId = currentRaffle.getId();

    if (newEntryForename==null || newEntrySurname == null || String.valueOf(addEntryTelephoneNo) == null || String.valueOf(addEntryTicketCount) == null){
    Intent failIntent = new Intent();
    } else {
        Entry newEntry = new Entry(newEntryForename, newEntrySurname, newEntryTelephoneNo, newEntryTicketCount, newEntryRaffleId);


        // Get the list of raffles
        for(Raffle currentEntryRaffle : Raffle.raffleArrayList) {
            if((currentEntryRaffle.getId() == newEntryRaffleId) && ((currentEntryRaffle.getEntryArrayList().size()) < (currentEntryRaffle.getMaxTickets()))) {
                int counter=0;
                do {
                    currentEntryRaffle.getEntryArrayList().add(newEntry);
                    counter++;
                } while(counter < newEntryTicketCount);
            }
        }

        Intent returnIntent = new Intent();
        setResult(RESULT_CANCELED, returnIntent);
        finish();
    }

You have to replace .equals(null) with == null since calling a method on a null pointer will crash your app.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM