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!
wo ist Ihre movie_list_fragment.xml? –
können Sie Ihre Xml? –
Warum? Weil 'findViewById' null zurückgeben kann. Das ist einfach. Ohne Ihr Layout zu sehen, ist die Antwort unten korrekt –