2016-04-20 5 views
1

Diese App zeigt Filme an und jedes Filmplakat kann angeklickt werden, um Details über den Film zu sehen. Wenn ich jedoch versuche, dem Detailansichtslayout eine Schaltfläche hinzuzufügen, stürzt die App mit diesen Fehlern ab. Wenn ich die Schaltfläche aus dem Layout entferne, funktioniert die App wie es sollte. Dieser Absturz scheint mir seltsam zu sein.Hinzufügen einer Schaltfläche zu einem Layout und Programmabstürze. Warum?

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) 

Hier ist mein Detail-Aktivitätscode.

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

}

Hier ist die Layout-Datei mit der Detailklasse zugeordnet

<?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"/> 

Hier wird die Filmliste Klasse

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

} 

}

Ich bin nicht sicher, was das verursachen könnte. Vielen Dank im Voraus für die Hilfe!

+1

wo ist Ihre movie_list_fragment.xml? –

+0

können Sie Ihre Xml? –

+0

Warum? Weil 'findViewById' null zurückgeben kann. Das ist einfach. Ohne Ihr Layout zu sehen, ist die Antwort unten korrekt –

Antwort

1

Der Stack-Trace sagt Ihnen:

Versuch virtuelle Methode 'Leere android.widget.GridView.setAdapter (android.widget.ListAdapter)' auf einem null Objektverweis aufrufen

Wo haben Sie setAdapter im Code aufgerufen?

mGridView.setAdapter(imageAdapter); 

Wie haben Sie versucht, es anzurufen?

mGridView 

Wie haben Sie den Hinweis darauf bekommen?

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

... was eindeutig Null zurückgibt. Finde jetzt heraus, warum es die Ansicht nicht finden kann.

Ich sehe nicht die ID movie_list_grid_view irgendwo in Ihrem Code.

+0

Ich habe eine Layout-Datei für die Liste Film Aktivität, die eine Gridview mit der ID movie_list_grid_view enthält. –

0

Können Sie den Inhalt dieser Datei movie_list_fragment.xml anzeigen? Ich denke, das Problem ist von dort. Vielleicht haben Sie die GridView eine andere ID als im Vergleich zu movie_list_grid_view.

+0

Das gesamte Projekt ist hier auf Gitgub. https://github.com/jmcs811/PopularMovies?files=1 –

Verwandte Themen