-1

I want to calculate the average of grades, now I have the basics and the layout. When the EditText is left open it throws a NullPointerException, I know what it is but not how I can check/handle it with my code. Can someone explain me how to do this?

Any tips etc. are welcome!

final TextView averageView = findViewById(R.id.averageView); 
final String averageText = getString(R.string.average); 
final Button calculateButton = findViewById(R.id.calculateAverageButton); 
final Button addGradeButton = findViewById(R.id.addGradeButton)

calaculateButton.setOnClickListener(new View.onClickListener() { 
    @SupressLint("SetTextI18n")                                                     
    public void onClick(View v) { 

        double grade[]  = {Double.parseDouble(((EditText) findViewById(R.id.grade1)).getText().toString()); 

        double weight[] = {Double.parseDouble(((EditText) findViewById(R.id.weight1)).getText().toString()); 

        double weightTotal = weight[0]; double sum = grade[0] * weight[0] 

        double average = sum / weightTotal 

        @SuppressLint("DefaultLocale") String averageResult = String.format(%.2f, average);

        averageView.setText(averageText + " " + averageResult);
J.doe
  • 27
  • 3
  • We need the stacktrace. – TheWanderer Dec 26 '18 at 19:45
  • I currently have no acces to the stacktrace, but the error is that i'm getting text from the EditText but there is nothing to get. (NullPointerException) as its empty. I'm looking for a way how I can check for empty/null value etc. – J.doe Dec 26 '18 at 19:53
  • no stacktrace is needed, if you attempt a toString() on a null it will cause an exception. Your question supplied adequate data to help you. Please see my answer. – Sam Dec 26 '18 at 20:21
  • Possible duplicate of [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – Roddy of the Frozen Peas Dec 26 '18 at 20:23

4 Answers4

1

So you have to be careful calling "toString()" on a potential null object.

Especially if you plan to cast it to a double.

Note* Your code also creates an array of doubles from a single entry in the EditText so additional checking of the text format before casting it should be done as well to ensure it is a double. You can take the lazy way and wrap it in a try/catch to tell them it isn't formatted properly if you would like.

Handling Number format exceptions means you need to confirm that it is a double before you use it. You can use a nice utility or you can write a simple helper method. Guava has a helper method, Apache has helper methods or you can write a regex pattern matcher like here. The nice thing about regex is that you aren't relying on a try/catch to identify an issue.

How to check that a string is parseable to a double?

But for sake of thoroughness you could do something like:

private boolean isDouble(String value) {
    try {
        Double.parseDouble(value);
        return true;
    } catch (Exception ex) {
        return false;
    }
}

You have a few options for handling your null.

1) Check for null in a "if / else" statement.

double grade[];
if (myText.getText() != null && isDouble(myText.getText().toString()) {
    grade = {Double.parseDouble(myText.getText().toString())}
} else {
    //it's null, don't use it
}

2) check for null inline

if (isDouble(myText.getText().toString()) {
    double grade[] = myText.getText() == null ? {0.0, 0.0} : {Double.parseDouble(myText.getText().toString())}
}

3) Allow null as an option

double grade[] = myText.getText() == null ? null : {Double.parseDouble(myText.getText().toString())}

4) Cheat and use a Try/Catch (if you don't want to master handling this the best ways, and just want to make sure it doesn't crash and you can notify the user of a data formatting issue, you can simply wrap a Try/Catch around all your code and say "not formatted properly" each time, but that is not very descriptive and possibly not helpful enough, just fyi.

5) Or if you are willing to use Kotlin you can make great extension methods for each.

fun EditText.doubleArrayOrDefault(): ArrayList<Double> {
      return if (this.getText() != null && isDouble(myText.getText().toString())) {
            {Double.parseDouble(myText.getText().toString())}
      } else {
            {0.0, 0.0} // or whatever you want your default to be
      }
 }

6) Lastly, you could simply use DataBinding which would always be my personal preference. Update your gradle to enable DataBining and accept the inevitable that it's the greatest thing to happen since sliced break ;).

in the Activity you would have

var myObservabeText: ObservableField<String> = ObservableField("defaultTextIfAny")

in the onCreate you would set the variable

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    mBinding = DataBindingUtil.setContentView(this, R.layout.activity_my)
    mBinding.activity = this
}

in the XML you would update it to be

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:bind="http://schemas.android.com/apk/res-auto">

    <data>
        <variable name="activity" type="com.package.a35.activities.MyActivity" />
    </data>

     <EditText
        android:id="@+id/myText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@={activity.myObservableText}" />

Of course you can also add a JVMStatic to an adapter to handle binding to an array of double as well, if you want to write a nice adapter that is pretty straight forward as well.

Of course this is all pseudo and not typed in the actual IDE, but it will be very close, so hopefully this will help you with options.

Best of luck, hopefully one of these options fits your needs nicely.

Happy Coding.

Sam
  • 5,342
  • 1
  • 23
  • 39
  • hi, thanks for the awesome explanation. I used the if/else statement, but now I have the error `java.lang.NumberFormatException: empty string` now I do not know what to do with this. – J.doe Dec 26 '18 at 21:07
  • @J.doe, Add this condition `if(myText.getText()!=null && !myText.getText().toString().isEmpty())` and give it try. – ॐ Rakesh Kumar Dec 27 '18 at 05:56
  • J.doe I mentioned in the Note* section that you need to confirm formatting. I also mentioned in option 4 that you could wrap with a try catch. I'll update to help you a bit further – Sam Dec 27 '18 at 13:41
0

You need to check if the edit text it's not null, you can do something like:

private String getGrade1() {
        if ((EditText) findViewById(R.id.grade1)).getText().toString() != null || 
        (EditText)findViewById(R.id.grade1)).getText().toString() != "") {
           return (EditText) findViewById(R.id.grade1)).getText().toString();
         } else {
         //show a toast saying the the user needs to fill this input
        }
0

You could simply check if the textview's text isn't null before parsing it, and then handle it properly.

TextView tvGrade1 = findViewById(R.id.grade1));
TextView tvWeight1 = findViewById(R.id.weight1));

if(tvGrade1.getText() == null || tvWeight1.getText() == null)
    //one of them is null, do stuff
urukh
  • 360
  • 1
  • 3
  • 17
-2

You can also simply wrap the whole code in the onClick() method inside a try-catch statement and then catch the exception and do the necessary tasks or display a toast error message to the user that he has not entered value in both fields.

Mohd Akbar
  • 111
  • 5