Good people, all right? I'm using a RecyclerView to popular my list on Android and for that I have an adapter and a view holder.
Follow Adapter source code with ViewHolder
public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MoviesViewHolder> {
private OnItemClicked onClick;
public interface OnItemClicked {
void onItemClick(int position);
}
private final List<Movie> moviesList;
private final Context context;
public MoviesAdapter(List<Movie> moviesList, Context context) {
this.moviesList = moviesList;
this.context = context;
}
@Override
public MoviesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
int layoutIdForItem = R.layout.filme_item;
LayoutInflater layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(layoutIdForItem, parent, false);
return new MoviesViewHolder(view);
}
@Override
public void onBindViewHolder(MoviesViewHolder holder, int position) {
Movie movie = moviesList.get(position);
String imagemUri = movie.getPosterPath();
Picasso
.with(context)
.load(imagemUri)
.into(holder.mPosterMovieImageView);
holder.mPosterMovieImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onClick.onItemClick(position);
}
});
}
@Override
public int getItemCount() {
return moviesList.size();
}
public class MoviesViewHolder extends RecyclerView.ViewHolder {
public final ImageView mPosterMovieImageView;
public MoviesViewHolder(View view) {
super(view);
mPosterMovieImageView = view.findViewById(R.id.iv_movies_poster);
}
}
public void setOnClick(OnItemClicked onClick) {
this.onClick = onClick;
}
}
My app loads the entire movie list using Retrofit, but when you click on a movie, you should go to another activity to view details. But this OnClick is not working. Here is the code for my MainActivity
private static final String TAG = MainActivity.class.getSimpleName();
private RecyclerView mRecyclerView;
private MoviesAdapter mMoviesAdapter;
private List<Movie> movies = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews() {
mRecyclerView = (RecyclerView) findViewById(R.id.rv_lista_filmes);
GridLayoutManager gridManager = new GridLayoutManager(MainActivity.this, 2);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(gridManager);
loadPopularMovies();
}
private void loadPopularMovies() {
Call<MoviesDTO> call = new RetrofitStarter().getMovieService().retrievePopularMovies("api-key");
call.enqueue(new Callback<MoviesDTO>() {
@Override
public void onResponse(Call<MoviesDTO> call, Response<MoviesDTO> response) {
MoviesDTO moviesDTO = response.body();
movies = new ArrayList<>();
for (Movie movie : moviesDTO.getMovies()) {
movies.add(movie);
}
initAdapter(movies);
}
@Override
public void onFailure(Call<MoviesDTO> call, Throwable t) {
Log.e("ERROR", "error loading popular movies: " + t.getMessage());
}
});
}
private void initAdapter(List<Movie> movies) {
mMoviesAdapter = new MoviesAdapter(movies, MainActivity.this);
mRecyclerView.setAdapter(mMoviesAdapter);
}
private void loadTopRatedMovies() {
Call<MoviesDTO> call = new RetrofitStarter().getMovieService().retriveTopRatedMovies("api-key");
call.enqueue(new Callback<MoviesDTO>() {
@Override
public void onResponse(Call<MoviesDTO> call, Response<MoviesDTO> response) {
MoviesDTO moviesDTO = response.body();
movies = new ArrayList<>();
for (Movie movie : moviesDTO.getMovies()) {
movies.add(movie);
}
}
@Override
public void onFailure(Call<MoviesDTO> call, Throwable t) {
Log.e("ERROR", "error loading top rated movies: " + t.getMessage());
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
URL url = null;
int id = item.getItemId();
switch (id) {
case R.id.mi_popular:
loadPopularMovies();
break;
case R.id.mi_melhor_avaliado:
loadTopRatedMovies();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onItemClick(int position) {
Movie movie = movies.get(position);
Intent intentSelectedMovieDetail = new Intent(this, MovieDetailActivity.class);
intentSelectedMovieDetail.putExtra("selectedMovie", movie);
startActivity(intentSelectedMovieDetail);
}
This is the stack trace that generates when I try to click on an item
12-15 08:02:11.667 7551-7551/br.com.agilles.filmesfamosos E/AndroidRuntime: FATAL EXCEPTION: main
Process: br.com.agilles.filmesfamosos, PID: 7551
java.lang.NullPointerException: Attempt to invoke interface method 'void br.com.agilles.filmesfamosos.adapters.MoviesAdapter$OnItemClicked.onItemClick(int)' on a null object reference
at br.com.agilles.filmesfamosos.adapters.MoviesAdapter$1.onClick(MoviesAdapter.java:58)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)