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