Sahil Shokeen
Sahil Shokeen

Reputation: 336

Intent putExtra() not working

Hi in my MainActivity I implemented ViewPager with TabLayout with 3 tabs and each view page starts new Fragment. I am showing cards in a grid view in each Fragment and when a card is clicked DetailActivtiy starts. I am starting detail activity from Fragments but when I try to put some extra in Intent starting detail activity I get NullPointerException. I tried to debug code but I am unable to find where the problem is.

Here's my code:

PopularFragment(one of the tab layout in 3 tabs)

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

Here onClicked() method is called when any card of RecyclerView is clicked. 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);
    }
}
}

When I start DetailActivity without putting extra in Intent it works but when I put extra in Intent and try to retrieve it in DetailActivity I get NullPointerException. In DetailFragment(contained by DetailActivity i try to get intent as):

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

Here's the 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) 

Upvotes: 0

Views: 1194

Answers (1)

George Mulligan
George Mulligan

Reputation: 11903

You should not be using a static variable to hold the callback listener in your RecyclerAdapter. This means each RecyclerAdapter will always have the same callback listener when you want each one to have its own.

That is why you are experiencing this issue. RatedFragment and PopularFragment are both using a RecyclerAdapter. When you click an image the callback from your RatedFragment will be called even when viewing the PopulareFragmnet.

RatedFragment is then not adding the extra you are looking for which is causing the NullPointerException.

To fix this remove static from mListener in the RecyclerAdapter:

private OnClick mListener;

Then remove static also from the definition of the ViewHolder class so it becomes an inner class and can access the listener directly:

public class ViewHolder extends RecyclerView.ViewHolder
       implements View.OnClickListener {

After doing this you will still have to fix the RatedFragment since it will show the same DetailsFragment without the extra you are currently requiring.

Upvotes: 1

Related Questions