Onclick on android not working

0

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)
    
asked by anonymous 15.12.2017 / 14:10

1 answer

2

The object that should be used by the adapter to handle onClick has not been assigned.

I think it's your Activity that implements the MoviesAdapter.OnItemClicked interface, if so, it should be assigned to the adapter using the setOnClick() :

private void initAdapter(List<Movie> movies) {
    mMoviesAdapter = new MoviesAdapter(movies, MainActivity.this);

    mMoviesAdapter.setOnClick(this);

    mRecyclerView.setAdapter(mMoviesAdapter);
}
    
15.12.2017 / 14:21