Android 在布局中添加按钮,程序将崩溃。为什么?

Android 在布局中添加按钮,程序将崩溃。为什么?,android,list,android-layout,Android,List,Android Layout,此应用程序显示电影,可以单击每个电影海报以查看有关电影的详细信息。但是,当我尝试向详细视图布局添加按钮时,应用程序会因这些错误而崩溃。当我从布局中删除按钮时,应用程序将正常工作。这次撞车对我来说似乎很奇怪 04-19 20:05:53.479 28975-28975/com.jcaseydev.popularmovies E/AndroidRuntime: FATAL EXCEPTION: main Process: com.jcaseydev.popularmovies, PID: 28975

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

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

}
导入android.content.Intent;
导入android.net.Uri;
导入android.os.AsyncTask;
导入android.os.Bundle;
导入android.support.v4.app.Fragment;
导入android.util.Log;
导入android.view.LayoutInflater;
导入android.view.Menu;
导入android.view.MenuInflater;
导入android.view.MenuItem;
导入android.view.view;
导入android.view.ViewGroup;
导入android.widget.AdapterView;
导入android.widget.GridView;
导入org.json.JSONArray;
导入org.json.JSONException;
导入org.json.JSONObject;
导入java.io.IOException;
导入java.util.ArrayList;
导入java.util.List;
导入okhttp3.OkHttpClient;
导入okhttp3.请求;
导入okhttp3.响应;
公共类MovieListFragment扩展了片段{
private ArrayList movieArrayList=new ArrayList();
private ArrayList listOfMoviePosters=新ArrayList();
私有字符串MOVIE\u KEY=“MOVIE\u info”;
专用图像适配器;
专用字符串BASE_URL=”http://api.themoviedb.org/3/movie/now_playing";
int-toggle=0;
公共电影片段{
}
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
设置选项菜单(真);
}
私有void updateMovies(){
//把这两张表都清除掉
movieArrayList.clear();
moviemposter.clear()列表;
//创建一个新的异步任务并执行
FetchMovieData fmd=新的FetchMovieData();
fmd.execute();
}
@凌驾
CreateView上的公共视图(布局、充气机、视图组容器、捆绑包保存状态){
视图根视图=充气机。充气(R.layout.movie\u list\u片段,容器,false);
imageAdapter=新的imageAdapter(getActivity(),listOfMoviePosters);
GridView mGridView=(GridView)rootview.findviewbyd(R.id.movie\u list\u grid\u视图);
mGridView.setAdapter(imageAdapter);
mGridView.setOnItemClickListener(新的AdapterView.OnItemClickListener(){
@凌驾
public void onItemClick(AdapterView父对象、视图、整型位置、长id){
Movie details=movieArrayList.get(位置);
意向意向=新意向(getActivity(),DetailActivity.class)
.putExtra(电影键,细节);
星触觉(意向);
}
});
返回rootview;
}
@凌驾
public void onStart(){
super.onStart();
updateMovies();
}
公共类FetchMovieData扩展异步任务{
私有列表getDataFromJSon(字符串json)抛出JSONException{
//需要得到的物品
最后一个字符串数组\u OF_MOVIES=“results”;
最终字符串TITLE=“TITLE”;
最终字符串POSTER_PATH=“POSTER_PATH”;
最终字符串概述=“概述”;
最终字符串发布日期=“发布日期”;
最终字符串VOTE_AVERAGE=“VOTE_AVERAGE”;
最终字符串电影\u ID=“ID”;
//将json存储在json对象中
JSONObject JSONObject=新的JSONObject(json);
//获得实际的电影效果
JSONArray JSONArray=jsonObject.getJSONArray(电影的数组);
//获取循环数组的长度
int limit=jsonArray.length();
//创建电影列表
列表电影=新建ArrayList();
//循环播放阵列中的所有影片
对于(int i=0;imGridView.setAdapter(imageAdapter);
mGridView
GridView mGridView =(GridView)rootview.findViewById(R.id.movie_list_grid_view);