For fun I'm going through the Udacity Popular Movies App tutorial. I have set it so that there is a spinner in the toolbar that calls a sortMovies(String sortBy) method in my MainActivityFragment. The sortMovies() then calls GetMoviesTask.execute(sortBy).
When I run the program, everything works out fine. It displays the gridView of Movie posters sorted by Popularity which I have called in the onCreateView() of the MainActivityFragment.
However, when I click the spinner and choose to sort by "Highest Rated" it executes GetMoviesTask.execute properly (I checked the json being returned), but when it gets time to set the GridView adapter, it is saying the gridView is null.
Here is MainActivity:
public class MainActivity extends AppCompatActivity {
final String SORT_POPULARITY = "popularity.desc";
final String SORT_HIGHEST_RATED = "vote_average.desc";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Spinner spinner = (Spinner) findViewById(R.id.spinner_sort_by);
ArrayAdapter spinnerAdapter = ArrayAdapter.createFromResource(this,
R.array.spinner_sort_options,
R.layout.simple_spinner_layout_item);
spinner.setAdapter(spinnerAdapter);
spinnerAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
spinner.setSelection(0, false);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
MainActivityFragment mainActivityFragment;
mainActivityFragment = new MainActivityFragment();
switch (position) {
case 0:
mainActivityFragment.sortMovies(SORT_POPULARITY);
break;
case 1:
mainActivityFragment.sortMovies(SORT_HIGHEST_RATED);
break;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// sometimes you need nothing here
}
});
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Here is MainActivityFragment:
public class MainActivityFragment extends Fragment {
View rootView;
GridView gridView;
List<Movie> movies = new ArrayList<>();
public MainActivityFragment(){
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_main, container, false);
gridView = (GridView) rootView.findViewById(R.id.gridView);
GetMoviesTask getMoviesTask = new GetMoviesTask();
getMoviesTask.execute("popularity.desc");
return rootView;
}
@Override
public void onStart() {
super.onStart();
// GetMoviesTask getMoviesTask = new GetMoviesTask();
// getMoviesTask.execute();
}
public void sortMovies(String sortBy) {
GetMoviesTask getMoviesTask = new GetMoviesTask();
getMoviesTask.execute(sortBy);
}
public class GetMoviesTask extends AsyncTask<String, Void, String[]> {
@Override
protected String[] doInBackground(String... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String sortBy = params[0];
//Contains the Json Result
String moviesJson = null;
try {
final String API_BASE_URL = "http://api.themoviedb.org/3/discover/movie?";
final String API_KEY = "b96087f4a03b686eaf542c5df8037005";
final String API_KEY_PARAM = "api_key";
final String API_PAGE = "page";
final String API_SORT_BY = "sort_by";
Uri apiUri = Uri.parse(API_BASE_URL).buildUpon()
.appendQueryParameter(API_SORT_BY, sortBy)
.appendQueryParameter(API_PAGE, "1")
.appendQueryParameter(API_KEY_PARAM, API_KEY)
.build();
URL url = new URL(apiUri.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
moviesJson = null;
}else {
reader = new BufferedReader(new InputStreamReader(inputStream));
}
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
if (buffer.length() == 0) {
moviesJson = null;
}
////////////////////////////////////////////////////
//////////Return the json string containing the movies////////////
moviesJson = buffer.toString();
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} catch (NetworkOnMainThreadException e) {
Log.d("Error: ", e.toString());
}
try {
return getMoviesFromJson(moviesJson);
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String[] jsonMovieData) {
if (jsonMovieData != null) {
try {
gridView.setAdapter(new ImageAdapter(getContext(), jsonMovieData));
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
//pass the movie to the Detail Activity
Intent i = new Intent(getActivity(), MovieDetail.class);
i.putExtra("movie", movies.get(position));
startActivity(i);
}
});
} catch (NullPointerException e) {
e.printStackTrace();
}
} else
{
Toast.makeText(getContext(), "Nothing to show :(",
Toast.LENGTH_LONG).show();
}
}
}
private String[] getMoviesFromJson(String jsonMovieData) throws JSONException {
//Json Object(s) to be extracted
final String TMDB_POSTER = "poster_path";
final String TMDB_ORIGINAL_TITLE = "original_title";
final String TMDB_OVERVIEW = "overview";
final String TMDB_VOTE_COUNT = "vote_count";
final String TMDB_VOTE_AVERAGE = "vote_average";
final String TMDB_BACKDROP = "backdrop_path";
final String TMDB_BASE_POSTER_PATH = "http://image.tmdb.org/t/p/w500/";
final String TMDB_RESULTS = "results";
final String TMDB_ID = "id";
JSONObject moviesJson = new JSONObject(jsonMovieData);
JSONArray moviesArray = moviesJson.getJSONArray(TMDB_RESULTS);
String[] posterPaths = new String[moviesArray.length()];
// Extract movie data and build movie objects
for(int i = 0; i < moviesArray.length(); i++) {
Movie movie = new Movie();
JSONObject movieJson = moviesArray.getJSONObject(i);
movie.posterPath = TMDB_BASE_POSTER_PATH + movieJson.optString(TMDB_POSTER).toString();
posterPaths[i] = movie.posterPath;
movie.title = movieJson.optString(TMDB_ORIGINAL_TITLE).toString();
movie.description = movieJson.optString(TMDB_OVERVIEW).toString();
movie.title = movieJson.optString(TMDB_ORIGINAL_TITLE).toString();
movie.backDrop = movieJson.optString(TMDB_BACKDROP).toString();
movie.voteAverage = movieJson.optString(TMDB_VOTE_AVERAGE).toString();
movie.numOfVotes = movieJson.optString(TMDB_VOTE_COUNT).toString();
movies.add(movie);
}
return posterPaths;
}
}
As stated, when the app loads, the images load in the gridview perfectly fine, but when I select one of the spinners, in onPostExecute it says:
02-02 16:03:13.323 19412-19412/com.ferr3t.don.gurumovies W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.GridView.setAdapter(android.widget.ListAdapter)' on a null object reference
02-02 16:03:13.333 19412-19412/com.ferr3t.don.gurumovies W/System.err: at com.ferr3t.don.gurumovies.MainActivityFragment$GetMoviesTask.onPostExecute(MainActivityFragment.java:161)
I'm sure there is a simple solution that I am overlooking, however after 2 straight days, I've finally turned to stackOverflow...any help would be greatly appreciated.