GridView setAdapter方法给出了NullPointerException

时间:2016-02-07 14:43:01

标签: java android gridview android-adapter android-gridview

ArrayAdapter设置为GridView适配器时,我收到以下NullPointerException。该应用程序在运行时崩溃。

logcat的:

02-07 19:34:36.599: E/AndroidRuntime(26304): FATAL EXCEPTION: main
02-07 19:34:36.599: E/AndroidRuntime(26304): Process: com.shreyans.moviemania, PID: 26304
02-07 19:34:36.599: E/AndroidRuntime(26304): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.shreyans.moviemania/com.shreyans.moviemania.MainActivity}: android.view.InflateException: Binary XML file line #1: Error inflating class fragment
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2411)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2474)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.app.ActivityThread.access$800(ActivityThread.java:144)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1359)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.os.Handler.dispatchMessage(Handler.java:102)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.os.Looper.loop(Looper.java:155)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.app.ActivityThread.main(ActivityThread.java:5702)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at java.lang.reflect.Method.invoke(Native Method)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at java.lang.reflect.Method.invoke(Method.java:372)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1029)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)
02-07 19:34:36.599: E/AndroidRuntime(26304): Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class fragment
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:763)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.view.LayoutInflater.parseInclude(LayoutInflater.java:892)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:802)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at com.shreyans.moviemania.MainActivity.onCreate(MainActivity.java:17)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.app.Activity.performCreate(Activity.java:5958)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
02-07 19:34:36.599: E/AndroidRuntime(26304):    ... 10 more
02-07 19:34:36.599: E/AndroidRuntime(26304): Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.widget.ArrayAdapter.getCount(ArrayAdapter.java:330)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.widget.GridView.setAdapter(GridView.java:201)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at com.shreyans.moviemania.MainActivityFragment.onCreateView(MainActivityFragment.java:107)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1036)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1226)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1328)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2284)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:111)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:314)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:31)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:79)
02-07 19:34:36.599: E/AndroidRuntime(26304):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:733)
02-07 19:34:36.599: E/AndroidRuntime(26304):    ... 21 more

这是我的适配器类:

public class MovieAdapter extends ArrayAdapter<Movie>{
    private static final String LOG_TAG = MovieAdapter.class.getSimpleName();

    public MovieAdapter(Activity context, List<Movie> movieList) {
        super(context, 0, movieList);
    }

    @Override
    public View getView(int position, View recycledView, ViewGroup parent) {
        Movie movie = getItem(position);

        if (recycledView == null){
            recycledView = LayoutInflater.from(getContext()).inflate(
            R.layout.grid_item_movies, parent, false);
        }
        ImageView imageView = (ImageView) recycledView.findViewById(R.id.grid_item_movies_image);
        imageView.setAdjustViewBounds(true);
        String baseUrl= "http://image.tmdb.org/t/p/";
        final String SIZE="w185/";
        Picasso.with(getContext())
                .load(baseUrl + SIZE + movie.getPosterPath())
                .into(imageView);
        return recycledView;
    }
}

MainActivityFragment.java:

public class MainActivityFragment extends Fragment {
    private static final String LOG_TAG = "ServiceGenerator";
    public static final String API_BASE_URL = "http://api.themoviedb.org/3/";
    private String sortBy="popularity.desc"; //Default sorting order
    private ArrayList<Movie> movieArrayList;
    private MovieAdapter movieAdapter;

    public MainActivityFragment() {
    }

        private void onLoadMoviesEvent() {
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            // set your desired log level
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            OkHttpClient httpClient = new OkHttpClient();
            httpClient.interceptors().add(logging);

            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(API_BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(httpClient)
                    .build();

            MovieApiService movieApiService = retrofit.create(MovieApiService.class);

            Call<MovieResults> call = movieApiService.fetchMovies(BuildConfig.MY_MOVIE_DB_API_KEY, sortBy);

            call.enqueue(new Callback<MovieResults>(){
                @Override
                public void onResponse(Response<MovieResults> response, Retrofit retrofit1) {
                    MovieResults movieResults = response.body();
                    if (movieResults != null) {
                        Log.i(LOG_TAG, "Got requested object: " + movieResults.getTotalPages() + " results.");

                        movieArrayList = (ArrayList<Movie>) movieResults.getResults();

                        Log.i(LOG_TAG, "Retrieved arraylist with 1st movie: \n" +
                                "Name: " + movieArrayList.get(0).getTitle()+
                                "\nPoster path: " + movieArrayList.get(0).getPosterPath() +
                                "\nRelease Date: " + movieArrayList.get(0).getReleaseDate() +
                                "\nOverview: " + movieArrayList.get(0).getOverview());
                        movieAdapter.clear();
                        movieAdapter.addAll(movieArrayList);
                    }
                    else {
                        Log.e(LOG_TAG, "Getting null object of MovieResults");
                        try {
                            String string = response.errorBody().string();
                            Log.i(LOG_TAG, string);
                        }
                        catch (IOException e) {
                            Log.e(LOG_TAG, "IOException inside the response");
                        }
                    }

                }
                @Override
                public void onFailure(Throwable throwable) {
                    Log.i(LOG_TAG, "Retrofit response failure");
                }

            });
        }

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

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView =  inflater.inflate(R.layout.fragment_main, container, false);
        movieAdapter = new MovieAdapter(getActivity(), movieArrayList);

        GridView gridView = (GridView) rootView.findViewById(R.id.gridview);
        gridView.setAdapter(movieAdapter);
        onLoadMoviesEvent();
        return rootView;
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

    @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);
    }
}

2 个答案:

答案 0 :(得分:0)

您正在movieArrayList方法中初始化onLoadMoviesEvent()的值,并在movieAdapter = new MovieAdapter(getActivity(), movieArrayList);之后调用它。尝试在创建适配器之前调用此方法。

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView =  inflater.inflate(R.layout.fragment_main, container, false);
        onLoadMoviesEvent();
        movieAdapter = new MovieAdapter(getActivity(), movieArrayList);

        GridView gridView = (GridView) rootView.findViewById(R.id.gridview);
        gridView.setAdapter(movieAdapter);

        return rootView;
    }

答案 1 :(得分:0)

您正在使用异步请求加载数据。因此,当您在onCreateView()方法中实现适配器时,您的数据尚未加载且movieArrayList为null,这就是为什么它会抛出 NullPointerException 的时候你创建了适配器。

1)用空的初始化你的arraylist,以获得NPE:

private ArrayList<Movie> movieArrayList = new ArrayList<Movie>();

2)从notifyDataSetChanged()方法更新数据后致电onResponse(),刷新GridView

@Override
public void onResponse(Response<MovieResults> response, Retrofit retrofit1) {
       MovieResults movieResults = response.body();
       if (movieResults != null) {
            movieArrayList = (ArrayList<Movie>) movieResults.getResults();
            movieAdapter.clear();// no need for this line in the first call
            movieAdapter.addAll(movieArrayList);
            movieAdapter.notifyDataSetChanged();
        }

        // ....
 }