0

I'm just a beginner in android development. Recently I'm developing an app which converts a unit between other units. The code was growing very large & it became eventually cumbersome to maintain and finding, fixing bugs. So, I tried to split the MainActivity.java into other classes, but now the apps keeping crashing. Android Studio can build and run the project, but it no longer runs on my device.

MainActivity.java file contains

package com.gazzali.spinitmeow;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {

    Spinner spinnerMainChoice, spinnerInputChoice, spinnerOutputChoice;

    EditText getInputValueID;
    double inputValue;

    TextView outputValue;

    Button buttonConvert;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /* ------------ Main code Starts Here ----------------*/

        /* Main conversion Type choice with Spinner (Drop Down menu)*/
        spinnerMainChoice = findViewById(R.id.spinnerIDMainChoice);
        // [IMPORTANT] Set Spinner Click Listener
        spinnerMainChoice.setOnItemSelectedListener(this);
        // Create an ArrayAdapter using the string array and a default spinner layout
        ArrayAdapter<CharSequence> adapterMainChoice = ArrayAdapter.createFromResource(this,
                R.array.MainChoices_array, android.R.layout.simple_spinner_item);
        // Specify the layout to use when the list of choices appears
        adapterMainChoice.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        // Apply the adapter to the spinner
        spinnerMainChoice.setAdapter(adapterMainChoice);

        /* Input Conversion type choice with Spinner */
        spinnerInputChoice = findViewById(R.id.spinnerIDInputChoice);
        spinnerInputChoice.setOnItemSelectedListener(this);

        /* Output Conversion type choice with Spinner */

        spinnerOutputChoice = findViewById(R.id.spinnerIDOutputChoice);
        spinnerOutputChoice.setOnItemSelectedListener(this);

        /* for input and output fields */
        getInputValueID = findViewById(R.id.editTextIDInputValue);
        String inputValueString = getInputValueID.getText().toString();
        if(!TextUtils.isEmpty(inputValueString))
        {
            try
            {
                inputValue = Double.parseDouble(inputValueString);
            }
            catch (Exception e1)
            {
                e1.printStackTrace();
            }
        }
        outputValue = findViewById(R.id.textViewIDOutputValue);

    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
        // An item was selected. retrieve the selected item
        String selectedMainChoice = parent.getItemAtPosition(pos).toString();
        Log.i("Selected", selectedMainChoice);
        //Toast.makeText(MainActivity.this, "Selected: " + selectedMainChoice, Toast.LENGTH_SHORT).show();

/* This is where I made the separation ; previously the contents inside the spinnerSelects's setInputOutSpinner()
        was inside the MainActivity as a method */

        spinnerSelects spinnerSelects = new spinnerSelects();
        spinnerSelects.setInputOutputSpinners(selectedMainChoice);

    }


    @Override
    public void onNothingSelected(AdapterView<?> parent) {
        // Another interface callback
    }

}

spinnerSelects.java file contanis:

package com.gazzali.spinitmeow;

import android.widget.ArrayAdapter;

public class spinnerSelects extends MainActivity{

    protected void setInputOutputSpinners(String selectedMainChoice) {
        switch (selectedMainChoice)
        {
            case "Length": {
                spinnerInputChoice.setAdapter(new ArrayAdapter<CharSequence>(this,
                        android.R.layout.simple_spinner_dropdown_item,
                        getResources().getStringArray(R.array.LengthChoices_array)));

                spinnerOutputChoice.setAdapter(new ArrayAdapter<CharSequence>(this,
                        android.R.layout.simple_spinner_dropdown_item,
                        getResources().getStringArray(R.array.LengthChoices_array)));
            }
            break;

            case "Temperature": {
                spinnerInputChoice.setAdapter(new ArrayAdapter<CharSequence>(this,
                        android.R.layout.simple_spinner_dropdown_item,
                        getResources().getStringArray(R.array.TemperatureChoices_array)));

                spinnerOutputChoice.setAdapter(new ArrayAdapter<CharSequence>(this,
                        android.R.layout.simple_spinner_dropdown_item,
                        getResources().getStringArray(R.array.TemperatureChoices_array)));
            }
            break;

            case "Weight": {
                spinnerInputChoice.setAdapter(new ArrayAdapter<CharSequence>(this,
                        android.R.layout.simple_spinner_dropdown_item,
                        getResources().getStringArray(R.array.WeightChoices_array)));

                spinnerOutputChoice.setAdapter(new ArrayAdapter<CharSequence>(this,
                        android.R.layout.simple_spinner_dropdown_item,
                        getResources().getStringArray(R.array.WeightChoices_array)));
            }
            break;
        }
    }
}

The Logcat shows this traces,which is much alien to me.

2019-07-20 19:55:12.757 18958-18958/com.gazzali.spinitmeow E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.gazzali.spinitmeow, PID: 18958
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
    at android.content.ContextWrapper.getResources(ContextWrapper.java:91)
    at android.view.ContextThemeWrapper.getResourcesInternal(ContextThemeWrapper.java:127)
    at android.view.ContextThemeWrapper.getResources(ContextThemeWrapper.java:121)
    at android.support.v7.app.AppCompatActivity.getResources(AppCompatActivity.java:543)
    at com.gazzali.spinitmeow.spinnerSelects.setInputOutputSpinners(spinnerSelects.java:13)
    at com.gazzali.spinitmeow.MainActivity.onItemSelected(MainActivity.java:83)
    at android.widget.AdapterView.fireOnSelected(AdapterView.java:944)
    at android.widget.AdapterView.dispatchOnItemSelected(AdapterView.java:933)
    at android.widget.AdapterView.access$300(AdapterView.java:53)
    at android.widget.AdapterView$SelectionNotifier.run(AdapterView.java:898)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:201)
    at android.app.ActivityThread.main(ActivityThread.java:6810)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
2019-07-20 19:55:12.787 18958-18958/com.gazzali.spinitmeow I/Process: Sending signal. PID: 18958 SIG: 9

at com.gazzali.spinitmeow.spinnerSelects.setInputOutputSpinners(spinnerSelects.java:13) at com.gazzali.spinitmeow.MainActivity.onItemSelected(MainActivity.java:83)

these two lines have blue underlined whereas others in red.

Can someone please tell me where I need to fixe bugs so my doesn't crashes anymore? Thanks in Advance.

Arif Hamim
  • 59
  • 7
  • 1
    Use Logcat to examine the stack traces associated with your crashes: https://stackoverflow.com/questions/23353173/unfortunately-myapp-has-stopped-how-can-i-solve-this If you do not understand what the stack traces are telling you, edit your question and post the stack trace that comes from running the version of the code in the question. – CommonsWare Jul 20 '19 at 13:56

2 Answers2

1

For solving your current NullPointerException problem,

pass your activity context to your spinnerSelects desired method

spinnerSelects.setInputOutputSpinners(MainActivity.this,selectedMainChoice);

and in this method use that activity to getResources

protected void setInputOutputSpinners(Activity activity, String selectedMainChoice) {
        switch (selectedMainChoice)
        {
            case "Length": {
                spinnerInputChoice.setAdapter(new ArrayAdapter<CharSequence>(this,
                        android.R.layout.simple_spinner_dropdown_item,
                        activity.getResources().getStringArray(R.array.LengthChoices_array)));

                spinnerOutputChoice.setAdapter(new ArrayAdapter<CharSequence>(this,
                        android.R.layout.simple_spinner_dropdown_item,
                        activity.getResources().getStringArray(R.array.LengthChoices_array)));
            }
            break;


        }
    }

Hope it will solve your problem but in my opinion, your this code is not good. you can improve it.

if my solution did not work, don't extend MainActivity and keep the spinnerSelects as just a Java class and pass Spinner spinnerInputChoice variables to the desired class methods.

Happy coding!!!

majurageerthan
  • 2,169
  • 3
  • 17
  • 30
0

First of all you should not extend any Activity class in any other class. Instances of Activity classes would be created by Android system when you start them using an Intent. We should not create Activity instances using its constructor.

In spinnerSelects class, the spinnerInputChoice you are trying use is not part of the MainActivity's instance which was created by Android system. Because the instance of spinnerSelects you have created in onItemSelected method has different version of extended MainActivity.

Update

Check if following solve your problem:

  1. Remove MainActivity inheritense from spinnerSelects.
  2. In onItemSelected, supply context in spinnerSelects through constructor. You can use it to getResources.
public class spinnerSelects {
    private Context context;

    public spinnerSelects(Context pContext) {
        context = pContext;
    }

    // Your code

}
  1. Change setInputOutputSpinners method's return type to ArrayAdapter<CharSequence> and then return created ArrayAdapter<CharSequence> instance.
  2. In onItemSelected method set the returned adapter from setInputOutputSpinners to spinner.
krishh
  • 1,551
  • 15
  • 28
  • I get your point. So, How Do I modify the classes? I tried to using constructor but they are creating much more problem – Arif Hamim Jul 20 '19 at 14:12
  • @ArifHamim I did not get your question. But check if updated answer solve your problem. – krishh Jul 22 '19 at 13:55