【发布时间】:2016-06-16 23:24:02
【问题描述】:
我为横向模式和纵向模式使用了两种不同的布局。
花了几个小时后,我无法找出问题所在。 该应用程序在垂直启动时运行良好,在水平旋转时也运行良好。
当我从水平位置旋转回垂直位置并从列表中选择一个项目时,应用程序崩溃。
06-16 14:23:33.769 16108-16108/in.udacity.gagan.cinephilia E/AndroidRuntime: FATAL EXCEPTION: main
Process: in.udacity.gagan.cinephilia, PID: 16108
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.design.widget.CollapsingToolbarLayout.setTitle(java.lang.CharSequence)' on a null object reference
at in.udacity.gagan.cinephilia.DetailActivityFragment$3.onResponse(DetailActivityFragment.java:165)
at in.udacity.gagan.cinephilia.DetailActivityFragment$3.onResponse(DetailActivityFragment.java:148)
at com.android.volley.toolbox.JsonRequest.deliverResponse(JsonRequest.java:65)
at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
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)
主活动回调函数
@Override
public void onItemSelected(String id,
String backDrop,
String title,
int darkColor,
int lightColor) {
DetailActivityFragment displayFrag = (DetailActivityFragment) getSupportFragmentManager()
.findFragmentById(R.id.fragment_left);
if (displayFrag == null) {
Intent mIntent = new Intent(MainActivity.this, DetailActivity.class);
mIntent.putExtra("id", id);
mIntent.putExtra("backdrop_path", backDrop);
mIntent.putExtra("title", title);
mIntent.putExtra("darkColor", darkColor);
mIntent.putExtra("lightColor", lightColor);
startActivity(mIntent);
}
else
displayFrag.getContent(id, lightColor);}
详细活动片段函数
public void getContent(String id, int lightColor) {
fetchMovieDetails(id, lightColor);
}
FetchMovieDetails 函数
private void fetchMovieDetails(final String id, final int color){
mMovieDetail = null;
mDetailsList.clear();
String url = TmdbUrls.MOVIE_URL + id + "?" + BuildConfig.THE_MOVIE_DATABASE_API_KEY;
String reviewURL = TmdbUrls.MOVIE_URL + id + TmdbUrls.REVIEW + "?" + BuildConfig.THE_MOVIE_DATABASE_API_KEY;
Log.e("TAG", url);
JsonObjectRequest getDetails = new JsonObjectRequest(url,null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
String imageUrl = "http://image.tmdb.org/t/p/w780/" + response.getString("backdrop_path");
String iconImageURL="http://image.tmdb.org/t/p/w342/" + response.getString("poster_path");
String genres = "";
JSONArray genreArray = response.getJSONArray("genres");
for (int i = 0; i < genreArray.length(); i++) {
String genre = genreArray.getJSONObject(i).getString("name");
if (i != genreArray.length() - 1)
genres += genre + ", ";
else
genres += genre + ".";
}
mCollapsingToolbarLayout.setTitle(response.getString("title"));
mMovieDetail = new MovieDetail(id,
response.getString("title"),
response.getString("vote_average"),
genres,
response.getString("release_date"),
response.getString("status"),
response.getString("overview"),
iconImageURL,
imageUrl,
response.getString("tagline"),
response.getString("original_language"),
response.getString("runtime"),
response.getString("popularity"),
response.getString("vote_count")
);
Glide.with(getActivity())
.load(imageUrl)
.centerCrop()
.crossFade()
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.into(mImageView);
//fab.setBackgroundTintList(ColorStateList.valueOf(lightColor));
mDetailsList.add(mMovieDetail);
mAdapter = new DetailsAdapter(color, mDetailsList, mReviewList, mTrailersList, getActivity());
mRecyclerView.setAdapter(mAdapter);
boolean isMovieInDB = ContentProviderHelperMethods
.isMovieInDatabase(getActivity(),
String.valueOf(mMovieDetail.getId()));
if (isMovieInDB) {
fab.setImageDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.ic_like));
} else {
fab.setImageDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.ic_like_outline));
}
fab.show();
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
boolean isMovieInDB = ContentProviderHelperMethods
.isMovieInDatabase(getActivity(),
String.valueOf(mMovieDetail.getId()));
if (isMovieInDB) {
Uri contentUri = MoviesContentProvider.CONTENT_URI;
getActivity().getContentResolver().delete(contentUri, "id=?", new String[]{String.valueOf(mMovieDetail.getId())});
Snackbar.make(view, getResources().getString(R.string.removed_from_favourites), Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
fab.setImageDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.ic_like_outline));
} else {
ContentValues values = new ContentValues();
values.put(DatabaseHelper.KEY_ID, mMovieDetail.getId());
values.put(DatabaseHelper.KEY_TITLE, mMovieDetail.getTitle());
values.put(DatabaseHelper.KEY_RATING, mMovieDetail.getVote_average());
values.put(DatabaseHelper.KEY_GENRE, mMovieDetail.getGenre());
values.put(DatabaseHelper.KEY_DATE, mMovieDetail.getReleasedate());
values.put(DatabaseHelper.KEY_STATUS, mMovieDetail.getStatus());
values.put(DatabaseHelper.KEY_OVERVIEW, mMovieDetail.getOverview());
values.put(DatabaseHelper.KEY_BACKDROP, mMovieDetail.getBackdrop_path());
values.put(DatabaseHelper.KEY_VOTE_COUNT, mMovieDetail.getmVotecount());
values.put(DatabaseHelper.KEY_TAG_LINE, mMovieDetail.getmTagline());
values.put(DatabaseHelper.KEY_RUN_TIME, mMovieDetail.getmRuntime());
values.put(DatabaseHelper.KEY_LANGUAGE, mMovieDetail.getmLanguage());
values.put(DatabaseHelper.KEY_POPULARITY, mMovieDetail.getmPopularity());
values.put(DatabaseHelper.KEY_POSTER, mMovieDetail.getPoster_path());
getActivity().getContentResolver().insert(MoviesContentProvider.CONTENT_URI, values);
Snackbar.make(view, getResources().getString(R.string.added_to_favourites), Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
fab.setImageDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.ic_like));
}
}
});
fetchTrailerData(id);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
showSnackBar(getString(R.string.error_msg));
}
});
NetworkController.getInstance().addToRequestQueue(getDetails);
}
DetailActivityFragment onCreateView
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View rootView= inflater.inflate(R.layout.fragment_detail, container, false);
mCollapsingToolbarLayout = (CollapsingToolbarLayout) rootView.findViewById(R.id.collapsing_toolbar_layout_movie_details);
lightColor = getActivity().getIntent().getIntExtra("lightColor", 0);
id = getActivity().getIntent().getStringExtra("id");
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mToolbar = (Toolbar) rootView.findViewById(R.id.toolbar_movie_details);
mCollapsingToolbarLayout.setBackgroundColor(lightColor);
mCollapsingToolbarLayout.setContentScrimColor(lightColor);
mCollapsingToolbarLayout.setExpandedTitleColor(ContextCompat.getColor(getActivity(), android.R.color.transparent));
mCollapsingToolbarLayout.setCollapsedTitleTextColor(ContextCompat.getColor(getActivity(), android.R.color.white));
mImageView = (ImageView) rootView.findViewById(R.id.backdrop);
fab = (FloatingActionButton) rootView.findViewById(R.id.fab);
/*fab.setBackgroundTintList(ColorStateList.valueOf(lightColor));*/
mToolbar.setNavigationIcon(ContextCompat.getDrawable(getActivity(), R.drawable.ic_back));
mToolbar.inflateMenu(R.menu.menu_detail);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().finish();
}
});
mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == R.id.action_share) {
startActivity(Intent.createChooser(shareIntent(title), getResources().getString(R.string.share)));
return true;
}
return true;
}
});
fetchMovieDetails(id ,lightColor);
return rootView;
}
【问题讨论】:
-
你需要检查
mCollapsingToolbarLayout是否为空,当你旋转设备时它会被垃圾回收 -
DetailActivityFragment 包含与从 RecyclerView 中选择的项目相关的详细信息。那么,单击列表项应该再次为其分配内存吧?
-
如果 DetailActivityFragment 在选择某项时显示是,但您旋转之前的当前任务由于它被收集而不再具有该引用。我会将
getContent移动到片段的 oncreateView 中,这样当您的片段重新创建时,您就会获得真正属于您的问题的信息 -
@GhostCat 我的选择是建议编辑这个问题,因为这个问题还不够,用户只需复制粘贴 xml 并想要答案而不是尝试。我们希望他们编写代码,以便我们可以提供一些改进或正确性。
-
“编辑”表示:任何人都可以通过编辑修复问题(使其可回答)。但是这个问题是 A) 过于宽泛和 B) 非常不清楚(请参阅我给 OP 的 cmets)。因此,“编辑”或“确定”在这里都无效。这个问题需要由 OP 自己 重新处理,因此关闭它(因为太宽泛/不清楚)是唯一有效的选择。我希望这是有道理的。无论如何,我很欣赏快速而善良的回归。