0

The class below defines contents of a movie.

public class MovieCard {
String mAlbumArtURL;
String mName;
String mSynopsis;
String mRating;
String mReleaseDate;

public MovieCard(String albumArtURL, String name, String synopsis, String rating, String releaseDate) {
    this.mAlbumArtURL = albumArtURL;
    this.mName = name;
    this.mSynopsis = synopsis;
    this.mRating = rating;
    this.mReleaseDate = releaseDate;
}

public String getAlbumArtURL() {
    return mAlbumArtURL;
}

public void setAlbumArtURL(String mAlbumArtURL) {
    this.mAlbumArtURL = mAlbumArtURL;
}

public String getName() {
    return mName;
}

public void setName(String mName) {
    this.mName = mName;
}

public String getSynopsis() {
    return mSynopsis;
}

public void setSynopsis(String mSynopsis) {
    this.mSynopsis = mSynopsis;
}

public String getRating() {
    return mRating;
}

public void setRating(String mRating) {
    this.mRating = mRating;
}

public String getReleaseDate() {
    return mReleaseDate;
}

public void setReleaseDate(String mReleaseDate) {
    this.mReleaseDate = mReleaseDate;
}

}

The first activity of the app gives a list of movie album arts. The data for the rendering is fetched from an API. The data includes movie name, release date, plot synopsis, etc. But only the poster(album art) is shown in the first activity. Now, I assign an OnclickListener to the ViewHolder class, to start a new activity, whenever a user clicks on any of the posters. The second activity needs to contain the details of the movie poster clicked on. The entire data is fetched in the first activity's AsyncTask. I could start the new activity, but I am not able to understand how to send the required contents of the ViewHolder that is clicked on, to the second activity. I know that data is sent using 'putextra', but the issue is that i dont know what to send. I can only access the position of the ViewHolder, but not its content.

Here is the code for the adapter :

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MovieCardHolder> {

List<MovieCard> mMovieCards;
Context context;

public CustomAdapter(List<MovieCard> cards, Context c) {
    this.mMovieCards = cards;
    this.context = c;
}

@Override
public CustomAdapter.MovieCardHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_card, parent, false);
    MovieCardHolder movieCardHolder = new MovieCardHolder(view, context);
    return movieCardHolder;
}

@Override
public void onBindViewHolder(CustomAdapter.MovieCardHolder holder, int position) {
    holder.mMovieName.setText(mMovieCards.get(position).mName);
    Picasso.with(context).load(mMovieCards.get(position).mAlbumArtURL).into(holder.mMoviePoster);
}

@Override
public int getItemCount() {
    return mMovieCards.size();
}

public class MovieCardHolder extends RecyclerView.ViewHolder {
    ImageView mMoviePoster;
    TextView mMovieName;

    public MovieCardHolder(final View itemView, final Context context) {
        super(itemView);
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // Need details of the movie to be sent to the next activity.

                Intent intent = new Intent(context,MovieDetail.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(intent);
            }
        });
        mMoviePoster = (ImageView) itemView.findViewById(R.id.movie_poster);
        mMovieName = (TextView) itemView.findViewById(R.id.movie_name);
    }
}

}

Thanks in advance.

Arjun Issar
  • 672
  • 4
  • 13
  • 32

2 Answers2

2

You can attach the MovieCard to the root View;

public class MovieCardHolder extends RecyclerView.ViewHolder {
View root;
ImageView mMoviePoster;
TextView mMovieName;

public MovieCardHolder(final ViewGroup itemView, final Context context) {
    super(itemView);
    root = itemView;
    root.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

             // Need details of the movie to be sent to the next activity.
            MovieCard card = (MovieCard)v.getTag();
            Intent intent = new Intent(context, MovieDetail.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.putExtra("EXTRA_ART_URL", card.getAlbumArtURL());
            intent.putExtra("EXTRA_NAME", card.getName());
            intent.putExtra("EXTRA_Synopsis", card.getSynopsis());
            intent.putExtra("EXTRA_Rating", card.getRating());
            intent.putExtra("EXTRA_ReleaseDate", card.getReleaseDate());
            context.startActivity(intent);
        }
    });
    mMoviePoster = (ImageView) root.findViewById(R.id.movie_poster);
    mMovieName = (TextView) root.findViewById(R.id.movie_name);

    }
}

And:

@Override
public void onBindViewHolder(CustomAdapter.MovieCardHolder holder, int position) {
    holder.root.setTag(mMovieCards.get(position));
    holder.mMovieName.setText(mMovieCards.get(position).mName);
    Picasso.with(context).load(mMovieCards.get(position).mAlbumArtURL).into(holder.mMoviePoster);
}

In the MovieDetail method of onCreate()

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    String artUrl = getIntent().getStringExtra("EXTRA_ART_URL");
    //and so on to the rest of Strings
}
yshahak
  • 4,996
  • 1
  • 31
  • 37
  • Root is the View you inflated in onCreateViewHolder(). Look at my code, I added this View in your MovieCardHolder as field. – yshahak Aug 23 '15 at 09:40
  • Using this, I may just get the position of the View, whereas i need to get all the details of the movie pertaining to the poster clicked on. – Arjun Issar Aug 23 '15 at 09:40
  • You don't need anything because you added the instance of MovieCard as tag to the View that clicked and you get him back just by calling to getTag() – yshahak Aug 23 '15 at 09:42
  • So, now that I have the movie card, I just have to pass that object in the putextra and retrieve it in the next activity? – Arjun Issar Aug 23 '15 at 09:44
  • You can if you implement the class as Parceable, but you could just put the things you need with putExtra(), it easier. I can add it to answer if you don't know how – yshahak Aug 23 '15 at 09:45
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/87687/discussion-between-arjun-issar-and-yshahak). – Arjun Issar Aug 23 '15 at 09:46
  • @yshahak - I think ViewHolder or Adapter class should not be given responsibility to start an activity. Instead, an interface should be introduced which should send MovideCard object to either Activity or Fragment and from there one can start activity or load fragment. – Mohit Charadva May 19 '17 at 05:37
  • I don't argue that. I just kept the same logic of the original question. – yshahak May 19 '17 at 07:28
0

You can do a mMovieCards.get(position) to fetch the MovieCard you want.

You need to declare your MovieCard as Serializable by implementing it, like this:

class MovieCard implements Serializable

and send it through an Intent under putExtras(String key, Serializable value) Finally using your onBindViewHolder() callback.

@Override
public void onBindViewHolder(CustomAdapter.MovieCardHolder holder, int position) {
    // maybe declare a ViewGroup class member in your holder
    holder.parent.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Intent intent = new Intent(context, AnotherActivity.class);
                        intent.putExtra("my-object", mMovieCards.get(position));
                        context.startActivity(intent);
                    }
                });
}

In your another activity fetch your MovieCard like this:

MovieCard m = (MovieCard) getIntent().getSerializableExtra("my-object");
Rakeeb Rajbhandari
  • 5,043
  • 6
  • 43
  • 74