Search code examples
androidnullpointerexceptiononresume

Android: Unable to resume activity due to NullPointerException


Here is my onCreate() method:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        currentMeasurementType = DEFAULT_TYPE;

        final DataBaseHandler handler = new DataBaseHandler(getApplicationContext());
        SQLiteDatabase db = handler.getWritableDatabase();

        //Spinner for the measurement types
        final Spinner measurementTypesSpinner = (Spinner) findViewById(R.id.MeasurementTypes);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,
                handler.getMeasurementTypes());
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_item);
        measurementTypesSpinner.setAdapter(adapter);
        measurementTypesSpinner.setOnItemSelectedListener(this);

        //Spinner for the measurement sub types
        final Spinner measurementSubTypesSpinner = (Spinner) findViewById(R.id.MeasurementSubValues);
        try {
            ArrayAdapter<String> subAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,
                    handler.getMeasurementSubType(DEFAULT_TYPE));
            subAdapter.setDropDownViewResource(android.R.layout.simple_spinner_item);
            measurementSubTypesSpinner.setAdapter(subAdapter);
            //measurementSubTypesSpinner.setOnItemSelectedListener(this); TODO
        } catch(NonExistentMeasurementTypeException ex) {
            Log.d("failed to initialise the spinner for the measurement units", ex.getMessage());
        }

        //the value from which the user is converting from
        EditText value = (EditText) findViewById(R.id.unit_value);
        value.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
                unitValue = charSequence.toString();
                MeasurementType mType =
                        MeasurementType.getMeasurementType(measurementTypesSpinner.getSelectedItem().toString());
                String unitName = measurementSubTypesSpinner.getSelectedItem().toString();
                String unitValue = charSequence.toString();

                //create the converter
                Converter converter = new Converter(mType, unitName, unitValue);
                //convert the values
                ArrayList<Unit> convertedValues = converter.convert();
                //update the list view adapter
                updateUnitAdapter(convertedValues);
            }

            @Override
            public void afterTextChanged(Editable editable) {
                //nothing here
            }
        });

        //ListView
        ListView unitsView = (ListView) findViewById(R.id.units_list);
        unitsView.setItemsCanFocus(true);
        MeasurementType type = handler.getMeasurementType(DEFAULT_TYPE);
        final ArrayList<Unit> unitsConverted = new ArrayList<Unit>();
        unitsConverted.addAll(Arrays.asList(type.getUnits()));
        /**for some reason we need to do a clean up
         * also going to set the unit values to zero
         * for initialisation
         */
        for(Unit u : unitsConverted) {
            if(u == null) {
                unitsConverted.remove(u);
            } else {
                u.setValue(0.00);
            }
        }
        unitAdapter = new UnitListAdapter(this, unitsConverted, type);
        unitsView.setAdapter(unitAdapter);

        Button editList = (Button) findViewById(R.id.editList);
        editList.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                ArrayList<Unit> units = handler.getUnitsList(currentMeasurementType);
                Intent i = new Intent(getApplicationContext(), MeasurementTypeListActivity.class);
                i.putParcelableArrayListExtra("units", units);
                i.putExtra("measurementType", currentMeasurementType);
                startActivity(i);
            }
        });

    }

here is my onResume() method:

@Override
    protected void onResume() {
        super.onResume();

        SharedPreferences prefs = this.getSharedPreferences(
                "unitconverter", Context.MODE_PRIVATE);

        DataBaseHandler handler = new DataBaseHandler(getApplicationContext());

        //set the spinner for measurement type
        Spinner measurementTypeSpinner = (Spinner) findViewById(R.id.MeasurementTypes);
        ArrayAdapter adapter = (ArrayAdapter) measurementTypeSpinner.getAdapter();
        int typePos = adapter.getPosition(prefs.getString("currentmeasurementtype", "acceleration"));
        measurementTypeSpinner.setSelection(typePos);

        //set the spinner for the measurement unit
        Spinner measurementUnitSpinner = (Spinner) findViewById(R.id.MeasurementSubValues);
        ArrayAdapter arrayAdapter = (ArrayAdapter) measurementUnitSpinner.getAdapter();
        int unitPos = arrayAdapter.getPosition(prefs.getString("currentmeasurementunit", "centigal"));
        measurementUnitSpinner.setSelection(unitPos);

        //set the value
        EditText value = (EditText) findViewById(R.id.unit_value);
        value.setText(prefs.getString("value", "0.00"));

        /**
         * The list view stuff
         */
        ListView unitsList = (ListView) findViewById(R.id.units_list);
        unitsList.setItemsCanFocus(true);
        MeasurementType mType = handler.getMeasurementType(prefs.getString("currentmeasurementtype", "acceleration"));
        //create the converter
        Converter converter = new Converter(MeasurementType.getMeasurementType(prefs.getString("currentmeasurementtype", "acceleration")), prefs.getString("currentmeasurementunit", "centigal"), prefs.getString("value", "0.00"));
        //convert the values
        ArrayList<Unit> convertedValues = converter.convert();

        //update the current adapter
        updateUnitAdapter(convertedValues);
    }

here is the stack trace:

java.lang.RuntimeException: Unable to resume activity {com.example.UnitConverter/com.example.UnitConverter.MyActivity}: java.lang.NullPointerException
            at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2788)
            at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2817)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2250)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
            at com.example.UnitConverter.MyActivity$1.onTextChanged(MyActivity.java:78)
            at android.widget.TextView.sendOnTextChanged(TextView.java:7408)
            at android.widget.TextView.setText(TextView.java:3816)
            at android.widget.TextView.setText(TextView.java:3671)
            at android.widget.EditText.setText(EditText.java:80)
            at android.widget.TextView.setText(TextView.java:3646)
            at com.example.UnitConverter.MyActivity.onResume(MyActivity.java:243)
            at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1192)
            at android.app.Activity.performResume(Activity.java:5310)
            at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2778)
            at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2817)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2250)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)

so it is trying to do this:

at com.example.UnitConverter.MyActivity$1.onTextChanged(MyActivity.java:78)

after which it goes here:

at com.example.UnitConverter.MyActivity.onResume(MyActivity.java:243)

when I look at line 78 I can see this:

String unitName = measurementSubTypesSpinner.getSelectedItem().toString();

so It is trying to set this variable and it looks like it is going to line 242 to do this and line 242 reads this:

EditText value = (EditText) findViewById(R.id.unit_value);
value.setText(prefs.getString("value", "0.00"));

These are actually line 241 and 242, before it is suggested that I haven't initialised the EditText. But my thought was that trying to get the String from the preferences was returning null...because it might not have been saved.


Solution

  • From the docs for getSelectedItem:

    Returns The data corresponding to the currently selected item, or null if there is nothing selected.

    My guess is that your spinner has nothing selected so you get a NPE when you try to call toString() on the returned null value. You need to check that you got something back and set a default value if it is null.