您好MainActivity
我使用ViewPager
TabLayout
实施了3个标签,每个视图页面都会启动新的片段。我在每个片段的网格视图中显示卡片,当点击卡片时DetailActivtiy
开始。
我正在从Fragments开始详细活动,但是当我尝试在Intent
开始详细活动中添加一些额外内容时,我得到NullPointerException
。我试图调试代码,但我无法找到问题所在。
这是我的代码:
PopularFragment
(3个标签中的标签布局之一)
public class PopularFragment extends Fragment implements PosterTask.GetPoster,RecyclerAdapter.OnClick {
private RecyclerAdapter mRecyclerAdapter;
private ProgressDialog mProgressBar;
private ArrayList<Movie> movies;
public PopularFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_popular, container, false);
//Show progress bar
showProgressBar();
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
//Setting layout manager
recyclerView.setLayoutManager(new GridLayoutManager(inflater.getContext(), 2));
//Setting adapter
mRecyclerAdapter = new RecyclerAdapter(inflater.getContext());
recyclerView.setAdapter(mRecyclerAdapter);
return view;
}
@Override
public void onStart() {
super.onStart();
//Starting asyncTask
new PosterTask(this).execute(buildUrl().toString());
//Setting listener to cards
mRecyclerAdapter.setOnClickListener(this);
}
//Building url
private Uri buildUrl(){
//Building url
String api_key = "api_key";
return Uri.parse(Utility.POPULAR_URL).buildUpon()
.appendQueryParameter(api_key, getString(R.string.API_KEY))
.build();
}
//Called after getting posters url's
@Override
public void onPosterCompleted(ArrayList<Movie> movies) {
ArrayList<String> poster = new ArrayList<>();
for(int i=0;i<movies.size();i++){
poster.add(movies.get(i).getPoster());
}
//Passing data to adapter
mRecyclerAdapter.setPoster(poster);
//Removing progress bar
mProgressBar.hide();
this.movies = movies;
}
//Showing progress bar
private void showProgressBar(){
mProgressBar = new ProgressDialog(getContext());
mProgressBar.setMessage("Fetching data...");
mProgressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressBar.show();
}
@Override
public void onClicked(int position, View v) {
//Starting detail activity
Intent intent = new Intent(getActivity(), DetailActivity.class);
intent.putExtra(Utility.INTENT_CONSTANT, "sahil");
startActivity(intent);
}
}
当点击onClicked()
的任何卡片时,系统会调用此RecyclerView
方法。
RecyclerAdapter
:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private Context mContext;
private ArrayList<String> mPosters;
private static OnClick mListener;
//Listener listening clicks
public interface OnClick{
void onClicked(int position, View v);
}
public RecyclerAdapter(Context context){
mContext = context;
}
//Set poster url
public void setPoster(ArrayList<String> poster){
mPosters = poster;
notifyDataSetChanged();
}
//Set listener
public void setOnClickListener(OnClick listener){
mListener = listener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.card_layout, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//Loading url images to image view in cards
Picasso.with(mContext).load(mPosters.get(position)).into(holder.imageView);
}
@Override
public int getItemCount() {
if(mPosters!=null) {
return mPosters.size();
}
return 0;
}
//View holder for adapter
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private ImageView imageView;
public ViewHolder(View itemView) {
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.card_image);
imageView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
mListener.onClicked(getPosition(), v);
}
}
}
当我开始DetailActivity
而没有在Intent
中添加额外内容时,它可以正常工作,但当我在Intent
中添加额外内容并尝试在DetailActivity
中检索它时,我得NullPointerException
}。
在DetailFragment
中(由DetailActivity
包含,我试图获得意图):
//Exception:Detailfragment:
public class DetailFragment extends Fragment implements TrailerRecyclerAdapter.OnClick,TrailerTask.TrailerCompleted {
@Bind(R.id.movie_title)TextView titleView;
@Bind(R.id.movie_date)TextView dateView;
@Bind(R.id.movie_image)ImageView imageView;
@Bind(R.id.movie_vote_avg)TextView voteView;
@Bind(R.id.movie_votes)TextView totalView;
@Bind(R.id.favorite_button)Button favButton;
@Bind(R.id.trailer_view)RecyclerView trailerView;
@Bind(R.id.review_view)RecyclerView reviewView;
private TrailerRecyclerAdapter mTrailerAdapter;
private ArrayList<String> mTrailers;
public DetailFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_detail, container, false);
//Binding views
ButterKnife.bind(this, view);
//Getting clicked movie
// Movie movie = getActivity().getIntent().getParcelableExtra(Utility.INTENT_CONSTANT);
//Starting asyncTask
// new TrailerTask(this).execute(movie.getId());
//Binding data
// bindData(movie);
Log.v("title", getActivity().getIntent().getStringExtra(Utility.INTENT_CONSTANT));
return view;
}
//Binds data to views
/*
private void bindData(Movie movie){
titleView.setText(movie.getTitle());
dateView.setText(movie.getDate());
Picasso.with(getContext()).load(movie.getBack_poster()).into(imageView);
voteView.setText(String.valueOf(movie.getVote_avg()));
String total = getString(R.string.before) + movie.getTotal_votes() + getString(R.string.after);
totalView.setText(total);
//Setting adapter to trailerView
mTrailerAdapter = new TrailerRecyclerAdapter(getContext());
trailerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
trailerView.setAdapter(mTrailerAdapter);
}
*/
@Override
public void onClicked(int position, View v) {
//Building intent
Uri uri = Uri.parse(mTrailers.get(position)).buildUpon().build();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);
if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivity(intent);
}
}
@Override
public void onTrailerCompleted(ArrayList<String> trailers, ArrayList<String> trailer_posters) {
mTrailers = trailers;
mTrailerAdapter.setPoster(trailer_posters);
}
}
这里是Github repo
logcat的:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.movies, PID: 14578
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.movies/com.example.android.movies.DetailActivity}: android.view.InflateException: Binary XML file line #1: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2338)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class fragment
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713)
at android.view.LayoutInflater.parseInclude(LayoutInflater.java:816)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:745)
at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
at com.example.android.movies.DetailActivity.onCreate(DetailActivity.java:14)
at android.app.Activity.performCreate(Activity.java:5292)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1088)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2302)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException: println needs a message
at android.util.Log.println_native(Native Method)
at android.util.Log.v(Log.java:118)
at com.example.android.movies.DetailFragment.onCreateView(DetailFragment.java:54)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1036)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1226)
at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1328)
at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2284)
at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:111)
at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:314)
at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:31)
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:79)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:689)
at android.view.LayoutInflater.parseInclude(LayoutInflater.java:816)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:745)
at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
at com.example.android.movies.DetailActivity.onCreate(DetailActivity.java:14)
at android.app.Activity.performCreate(Activity.java:5292)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1088)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2302)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
at dalvik.system.NativeStart.main(Native Method)
答案 0 :(得分:1)
您不应该使用静态变量来保存RecyclerAdapter
中的回调侦听器。这意味着当您希望每个RecyclerAdapter
拥有自己的回调侦听器时,它们将始终具有相同的回调侦听器。
这就是您遇到此问题的原因。 RatedFragment
和PopularFragment
都使用RecyclerAdapter
。当您点击图片时,即使查看RatedFragment
,系统也会调用您PopulareFragmnet
的回调。
RatedFragment
然后没有添加您正在寻找导致NullPointerException
的额外内容。
要解决此问题,请从RecyclerAdapter
:
private OnClick mListener;
然后从ViewHolder
类的定义中删除静态,使其成为内部类,并可以直接访问监听器:
public class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
完成此操作后,您仍然需要修复RatedFragment
,因为它会显示相同的DetailsFragment
而没有您当前需要的额外费用。