此应用程序显示电影,每个电影海报都可以单击以查看有关电影的详细信息。但是,当我尝试在详细视图布局中添加按钮时,应用会因这些错误而崩溃。当我从布局中删除按钮时,应用程序将按预期工作。这次崩溃对我来说似乎很奇怪。

04-19 20:05:53.479 28975-28975/com.jcaseydev.popularmovies E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.jcaseydev.popularmovies, PID: 28975
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.jcaseydev.popularmovies/com.jcaseydev.popularmovies.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.GridView.setAdapter(android.widget.ListAdapter)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.GridView.setAdapter(android.widget.ListAdapter)' on a null object reference
at com.jcaseydev.popularmovies.MovieListFragment.onCreateView(MovieListFragment.java:72)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:339)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:602)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1237)
at android.app.Activity.performStart(Activity.java:6268)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
at android.app.ActivityThread.-wrap11(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5417) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)


这是我的详细活动代码。

package com.jcaseydev.popularmovies;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;


public class DetailFragment extends Fragment{
public DetailFragment(){}
Movie movie;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.detail_fragment, container, false);

    //get intent
    Intent intent = getActivity().getIntent();

    //key for the intent extra
    String MOVIE_INFO = "movie_info";

    //test if intent is null and if it has the correct extra
    if(intent != null && intent.hasExtra(MOVIE_INFO)){
        //fill movie with the details of the clicked item
        movie = intent.getParcelableExtra(MOVIE_INFO);

        //update view with all of the details
        updateView(rootView);
    }

    return rootView;
}
private void updateView(View view){
    //set up the views
    TextView title = (TextView) view.findViewById(R.id.movieTitle);
    TextView overview = (TextView)view.findViewById(R.id.movieOverview);
    TextView releaseDate = (TextView)view.findViewById(R.id.movieReleaseDate);
    ImageView moviePoster = (ImageView)view.findViewById(R.id.moviePoster);
    TextView movieVoteAvg = (TextView)view.findViewById(R.id.movieVote);


    //set the text on the views
    title.setText(movie.getMovieTitle());
    overview.setText(movie.getMovieOverview());
    releaseDate.setText(movie.getMovieReleaseDate());
    Picasso.with(getActivity()).load(movie.getMoviePoster()).into(moviePoster);
    movieVoteAvg.setText(Double.toString(movie.getMovieVoteAverage()));
}


}

这是与detailview类关联的布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/moviePoster"
    android:contentDescription="@string/movie_poster" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/movieReleaseDate" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/movieVote"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/movieTitle" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/movieOverview" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button"/>




这是电影列表类

import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;


public class MovieListFragment extends Fragment {

private ArrayList<Movie> movieArrayList = new ArrayList<>();
private ArrayList<String> listOfMoviePosters = new ArrayList<>();
private String MOVIE_KEY = "movie_info";
private ImageAdapter imageAdapter;
private String BASE_URL = "http://api.themoviedb.org/3/movie/now_playing";
int toggle = 0;

public MovieListFragment(){
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

private void updateMovies() {
    //clear out both lists
    movieArrayList.clear();
    listOfMoviePosters.clear();

    //create a new async task and execute
    FetchMovieData fmd = new FetchMovieData();
    fmd.execute();
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootview = inflater.inflate(R.layout.movie_list_fragment, container, false);

    imageAdapter = new ImageAdapter(getActivity(), listOfMoviePosters);

    GridView mGridView = (GridView) rootview.findViewById(R.id.movie_list_grid_view);
    mGridView.setAdapter(imageAdapter);

    mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Movie details = movieArrayList.get(position);
            Intent intent = new Intent(getActivity(), DetailActivity.class)
                    .putExtra(MOVIE_KEY, details);
            startActivity(intent);
        }
    });

    return rootview;
}

@Override
public void onStart() {
    super.onStart();
    updateMovies();
}

public class FetchMovieData extends AsyncTask<Void, Void, List<Movie>> {

    private List<Movie> getDataFromJSon(String json)throws JSONException{

        //items that need to be got
        final String ARRAY_OF_MOVIES = "results";
        final String TITLE = "title";
        final String POSTER_PATH = "poster_path";
        final String OVERVIEW = "overview";
        final String RELEASE_DATE = "release_date";
        final String VOTE_AVERAGE = "vote_average";
        final String MOVIE_ID = "id";

        //store the json in a json object
        JSONObject jsonObject = new JSONObject(json);

        //get the actual movie results
        JSONArray jsonArray = jsonObject.getJSONArray(ARRAY_OF_MOVIES);

        //get the length of the array for looping
        int limit = jsonArray.length();

        //creat a list of movies
        List<Movie> movies = new ArrayList<>();

        //loop through all of the movies in the array
        for(int i = 0; i < limit; i++){
            //get the current movie object
            JSONObject movieObject = jsonArray.getJSONObject(i);

            //get the various details about the movie
            String title = movieObject.getString(TITLE);
            String poster = "http://image.tmdb.org/t/p/w342/" + movieObject.getString(POSTER_PATH);
            String overview = movieObject.getString(OVERVIEW);
            String releasedate = movieObject.getString(RELEASE_DATE);
            Double voteAvg = movieObject.getDouble(VOTE_AVERAGE);
            int movieId = movieObject.getInt(MOVIE_ID);

            //add the movie object to the movie list
            movies.add(new Movie(title, poster, overview, releasedate, voteAvg, movieId));
        }

        return movies;
    }


    @Override
    protected List<Movie> doInBackground(Void... params) {

        try {

            final String QUERY_API = "api_key";

            //Build URL to get data from
            Uri builtUri = Uri.parse(BASE_URL).buildUpon()
                    .appendQueryParameter(QUERY_API, BuildConfig.TMDB_API_KEY)
                    .build();

            Log.d("URL", builtUri.toString());
            //Using OkHttp to make network request
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder()
                    .url(builtUri.toString())
                    .build();

            //creating a response object
            Response response = null;

            try {
                //attempt to execute request
                response = client.newCall(request).execute();
            } catch (IOException e) {
                e.printStackTrace();
            }

            //Storing results of request in a string
            String jsonData = response.body().string();

            try {
                //attempt to call method that will extract data
                return getDataFromJSon(jsonData); //call to extract data
            } catch (JSONException e) {
                e.printStackTrace();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(List<Movie> result) {
        if (result != null){
            //add all of the movie objects that have be gathered
            //into the movieArrayList
            movieArrayList.addAll(result);
            //Call updatePoster to get movie posters
            updatePoster();

            //notify the image adapter that there is data now
            imageAdapter.notifyDataSetChanged();

        }
    }
    public void updatePoster(){
        //for every movie in movieArraylist add to
        //listOfMoviePosters
        for (Movie movie : movieArrayList){
            listOfMoviePosters.add(movie.getMoviePoster());
        }
    }
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.movie_list_fragment_menu, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    //simple way to toggle the sort order
    if(id == R.id.sort_action) {
        if (toggle == 0) {
            BASE_URL = "http://api.themoviedb.org/3/movie/top_rated";
            movieArrayList.clear();
            listOfMoviePosters.clear();
            updateMovies();
            toggle = 1;
        } else if(toggle == 1){
            BASE_URL = "http://api.themoviedb.org/3/movie/now_playing";
            movieArrayList.clear();
            listOfMoviePosters.clear();
            updateMovies();
            toggle = 0;
        }
    }
        return super.onOptionsItemSelected(item);

}


}

我不确定是什么原因造成的。先谢谢您的帮助!

最佳答案

堆栈跟踪告诉您:


  尝试调用虚方法'void
  android.widget.GridView.setAdapter(android.widget.ListAdapter)'
  空对象引用


您在代码中的哪里调用了setAdapter

mGridView.setAdapter(imageAdapter);


您尝试调用什么?

mGridView


您是如何获得参考的?

GridView mGridView =(GridView)rootview.findViewById(R.id.movie_list_grid_view);


...显然返回null。因此,现在只需弄清楚为什么找不到视图即可。

在您的代码中的任何地方都看不到ID movie_list_grid_view

10-07 19:23
查看更多