为了好玩,我要浏览Udacity Popular Movies App教程。我已经设置它,以便工具栏中有一个微调器,它调用MainActivityFragment中的sortMovies(String sortBy)方法。然后sortMovies()调用GetMoviesTask.execute(sortBy)。
当我运行程序时,一切正常。它显示了按人气排序的电影海报的gridView,我在MainActivityFragment的onCreateView()中调用了它。
然而,当我点击微调器并选择按"最高等级"它正确执行GetMoviesTask.execute(我检查了返回的json),但是当它有时间设置GridView适配器时,它表示gridView为null。
这是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);
}
}
这是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;
}
}
如上所述,当应用程序加载时,网格视图中的图像加载完全正常,但是当我选择其中一个微调器时,在onPostExecute中它会显示:
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)
我确信有一个简单的解决方案,我忽略了,但是连续两天后,我终于转向stackOverflow ...任何帮助都将不胜感激。
答案 0 :(得分:0)
而不是创建新的片段MainActivityFragment mainActivityFragment;
mainActivityFragment = new MainActivityFragment();
您应该在当前活动中找到现有的片段。当您创建一个新的但片段尚未附加到活动时,则不会调用createView()
方法,从而导致空指针异常。
要查找现有片段: