Reputation: 775
I am attempting to change the items in a spinner using the ArrrayAdapter, with spinner.setAdapter(adapter)
This code runs when a sidebar item is selected, changing the values in the spinner
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
String Tag = "Navigation drawer";
Log.v(Tag, "Drawer item toggled");
Spinner spinner = (Spinner) getView().findViewById(R.id.inputSpinner);
//Get view must be used in order to use findViewById inside a fragment
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity().getApplicationContext(), //getActivity gets the correct context for me
R.array.area_units_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); //Tells the adapter what layout to use
spinner.setAdapter(adapter);
return true;
}
return super.onOptionsItemSelected(item);
}
The error that is thrown is the following
06-21 19:44:09.688 4715-4715/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.anapp.tpb.sidebarproject, PID: 4715
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Spinner.setAdapter(android.widget.SpinnerAdapter)' on a null object reference
at com.anapp.tpb.sidebarproject.NavigationDrawerFragment.onOptionsItemSelected(NavigationDrawerFragment.java:272)
at android.app.Fragment.performOptionsItemSelected(Fragment.java:2159)
at android.app.FragmentManagerImpl.dispatchOptionsItemSelected(FragmentManager.java:1988)
at android.app.Activity.onMenuItemSelected(Activity.java:2888)
at com.android.internal.widget.ToolbarWidgetWrapper$1.onClick(ToolbarWidgetWrapper.java:182)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
--------- beginning of system
I have read through other people with this NullPointer exception, and I can see that it is coming from the line Spinner spinner = (Spinner) getView().findViewById(R.id.inputSpinner);
however I don't know why. The spinner 'inputSpinner' exists.
I apologise if there is an obvious answer to this question. I just finished my GCSEs and prior to this have only really used Python. Java is relatively new to me, so I am making a simple unit converter app.
Upvotes: 0
Views: 225
Reputation: 775
In the end I fixed the problem using the public void onNavigationDrawerItemSelected(int position) {
in MainActivity, which runs on an item being selected.
I modified it to take a position argument, and then placed the ArrayAdapter code inside it, using if statements to load different arrays based on the nav drawer item selected.
However, I couldn't update the spinner within this code, so used a method to update the spinner.
kpublic void setAdapter(ArrayAdapter items){
Spinner inputSpinner = (Spinner) findViewById(R.id.inputSpinner);
Spinner outputSpinner = (Spinner) findViewById(R.id.outputSpinner);
inputSpinner.setAdapter(items);
outputSpinner.setAdapter(items);
String Tag = "setAdapter function";
Log.v(Tag, "Function has been called");
}
The next problem that I ran into is that upon the app being opened, the onNavigationDrawerItemSelected method is called. This led to a force close problem, as the method tried to add items to a spinner which wasn't there yet. To fix this I created a variable counting the amount of times that the onNavigationDrawerItemSelected method was run, and added an if statement so that the spinner would only be updated if this value is larger than 0
public int drawerCount = 0;
@Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
Spinner inputSpinner = (Spinner) findViewById(R.id.inputSpinner);
Spinner outputSpinner = (Spinner) findViewById(R.id.outputSpinner);
//Get view must be used in order to use findViewById inside a fragment
if (position == 1) {
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, //getActivity gets the correct context for me
R.array.area_units_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); //Tells the adapter what layout to use
setAdapter(adapter);
String Tag = "Spinner update";
Log.v(Tag, "Position 0 has been selected");
} else if(position == 2){
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, //getActivity gets the correct context for me
R.array.data_units_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); //Tells the adapter what layout to use
setAdapter(adapter);
String Tag = "Spinner update";
Log.v(Tag, "Position 2 has been selected");
} else if(position == 3){
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, //getActivity gets the correct context for me
R.array.density_units_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); //Tells the adapter what layout to use
setAdapter(adapter);
String Tag = "Spinner update";
Log.v(Tag, "Position 3 has been selected");
//The elif below runs only once the drawer has been opened once or more. It stops the app closing on startup
} else if(drawerCount > 0){ //This must be at the bottom or it mucks with the elifs below
//The line below checks if the change is actually needed, if the drawer item selected is Angle
if(position == 0){
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, //getActivity gets the correct context for me
R.array.angle_units_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); //Tells the adapter what layout to use
setAdapter(adapter);
String Tag = "Spinner update";
Log.v(Tag, "Position 0 has been selected");
}
}
drawerCount++;
String Tag = "Spinner update";
Log.v(Tag, "The drawerCount has been incremented it is equal to " + drawerCount);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, PlaceholderFragment.newInstance(position + 1))
.commit();
} //The function below is used to change the values in the two spinners.
//Doing this within the onNavigationDrawerItemSelected function caused a force close
public void setAdapter(ArrayAdapter items){
Spinner inputSpinner = (Spinner) findViewById(R.id.inputSpinner);
Spinner outputSpinner = (Spinner) findViewById(R.id.outputSpinner);
inputSpinner.setAdapter(items);
outputSpinner.setAdapter(items);
String Tag = "setAdapter function";
Log.v(Tag, "Function has been called");
}
Admittedly the code is a bit of a mess, but it works fine and isn't horribly slow, so it is not in need of immediate repair.
Upvotes: 0
Reputation: 204
Try changing Spinner spinner = (Spinner) getView().findViewById(R.id.inputSpinner);
to
Spinner spinner = (Spinner) findViewById(R.id.inputSpinner);
Because you cast it as a Spinner View with (Spinner)
and know the ViewID, there is no need to call getView()
then used the ID.
Not exactly sure if that solves it.
Also, use getApplicationContext()
only, again, there is no need to get the application context from the activity. Use getActivity()
(or getApplicationContext()
) stand-alone.
PS: Google Docs are AMAZING! Use them!
Upvotes: 1