java.lang.NullPointerException:尝试在 GridView 中的空对象引用上调用虚拟方法“java.lang.String java.lang.Object.toString()”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31109836/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference in GridView
提问by Shadab Khan
I am trying to get data about movies from the movie database. Then using a gridview in my layout I want to display it on my device. This I do by using an ArrayAdapter. I just want to diplay the names of the movies in a grid. But I keep getting "java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference" error. My code is as follows:
我正在尝试从电影数据库中获取有关电影的数据。然后在我的布局中使用 gridview 我想在我的设备上显示它。我通过使用 ArrayAdapter 来做到这一点。我只想在网格中显示电影的名称。但我不断收到“java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference”错误。我的代码如下:
public class MainActivityFragment extends Fragment {
ArrayAdapter<String> mMovieAdapter;
public MainActivityFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mMovieAdapter = new ArrayAdapter<String>(getActivity(), R.layout.item_movies, R.id.image_view_movie, new ArrayList<String>());
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
GridView listView = (GridView) rootView.findViewById(R.id.gridview_movies);
listView.setAdapter(mMovieAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(getActivity(), DetailActivity.class);
String forecast = mMovieAdapter.getItem(i);
intent.putExtra(Intent.EXTRA_TEXT, forecast);
startActivity(intent);
/*
* Context context = getActivity(); String forecast =
* mForecastAdapter.getItem(i); int duration =
* Toast.LENGTH_SHORT; Toast.makeText(context, forecast,
* duration).show();
*/
}
});
return rootView;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Inflate the menu; this adds items to the action bar if it is present.
inflater.inflate(R.menu.moviefragment, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_refresh) {
updateMovie();
return true;
}
return super.onOptionsItemSelected(item);
}
// TO update weather when activity starts
@Override
public void onStart() {
super.onStart();
updateMovie();
}
private void updateMovie() {
FetchMovieTask movieTask = new FetchMovieTask();
movieTask.execute();
}
class FetchMovieTask extends AsyncTask<Void, Void, String[]> {
private final String LOG_TAG = FetchMovieTask.class.getSimpleName();
@Override
protected String[] doInBackground(Void... params) {
/* if(params.length == 0) { return null; } */
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String movieJsonStr = null;
try {
// Construct the URL for the OpenWeatherMap query
// Possible parameters are avaiable at OWM's forecast API page,
// at
// http://openweathermap.org/API#forecast
final String BASE_URL = "http://api.themoviedb.org/3/discover/movie?";
final String QUERY_PARAM = "sort_by";
final String KEY_PARAM = "&api_key";
// Using UriBuilder
Uri builtUri = Uri.parse(BASE_URL).buildUpon().appendQueryParameter(QUERY_PARAM, "popularity.desc").appendQueryParameter(KEY_PARAM, "c20129fdf73b5df3ab44548ad7f73586").build();
URL url = new URL(builtUri.toString());
// Printing the url in the log
// Log.v(LOG_TAG, "Built URI " + builtUri.toString());
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it
// won't affect parsing)
// But it does make debugging a *lot* easier if you print
// out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
movieJsonStr = buffer.toString();
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the weather data, there's
// no point in attemping
// to parse it.
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
try {
return getMovieDataFromJson(movieJsonStr);
} catch (JSONException j) {
Log.e(LOG_TAG, "JSON Error", j);
}
return null;
}
private String[] getMovieDataFromJson(String forecastJsonStr) throws JSONException {
String title;
JSONObject movieJson = new JSONObject(forecastJsonStr);
JSONArray movieArray = movieJson.getJSONArray("results");
String[] resultStrs = new String[100];
for (int i = 0; i < movieArray.length(); i++) {
// Get the JSON object representing the day
JSONObject movie = movieArray.getJSONObject(i);
title = movie.getString("original_title");
resultStrs[i] = title;
Log.v(LOG_TAG, resultStrs[i]);
}
/*
* for (String s : resultStrs) { Log.v(LOG_TAG, "Forecast entry: " +
* s); }
*/
return resultStrs;
}
@Override
protected void onPostExecute(String[] strings) {
super.onPostExecute(strings);
mMovieAdapter.clear();
mMovieAdapter.addAll(strings);
}
}
}
And my error log is:
我的错误日志是:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:394)
at android.widget.ArrayAdapter.getView(ArrayAdapter.java:362)
at android.widget.AbsListView.obtainView(AbsListView.java:2344)
at android.widget.GridView.makeAndAddView(GridView.java:1433)
at android.widget.GridView.makeRow(GridView.java:361)
at android.widget.GridView.fillDown(GridView.java:302)
at android.widget.GridView.fillGap(GridView.java:262)
at android.widget.AbsListView.trackMotionScroll(AbsListView.java:4968)
at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:4512)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:549)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
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:5312)
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:901)
回答by Ivo Beckers
I suspect this is the error as also mentioned by Blackbelt in the comments
我怀疑这是 Blackbelt 在评论中也提到的错误
String[] resultStrs = new String[100];
This should be
这应该是
String[] resultStrs = new String[movieArray.length()];
Because what you now do is say to the GridView you have always100 movies but when there are less than 100 movies you are giving null elements to the GridView
因为您现在所做的是对 GridView 说您总是有100 部电影,但是当电影少于 100 部电影时,您将向 GridView 提供空元素