-1

I know this question is very but I am searched a lot and I am not able to understand the problem. I am creating an interface for handling click listeners on particular item on recycler view

Here are my classes

MovieAdapter.java

package com.example.vikas.movie.adapter;

/**
 * Created by vikas on 23/4/17.
 */
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.example.vikas.movie.R;
import com.example.vikas.movie.helper.CircleTransformation;
import com.example.vikas.movie.model.Movie;

import java.util.List;
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MovieViewHolder>
{
    private static final String TAG=MovieAdapter.class.getSimpleName();

    private List<Movie> movies;
    private int rowLayout;
    private Context context;
    private   MovieAdapterListener listener;


    public static class MovieViewHolder extends RecyclerView.ViewHolder
    {
       RelativeLayout moviesLayout;
        TextView movieTitle;
        TextView data;
        TextView movieDescription;
        TextView rating;
        ImageView imageView;


        public MovieViewHolder(View v)
        {
            super(v);
            moviesLayout = (RelativeLayout) v.findViewById(R.id.movie_layout);
            movieTitle = (TextView) v.findViewById(R.id.title);
            data = (TextView) v.findViewById(R.id.subtitle);
            movieDescription = (TextView) v.findViewById(R.id.description);
            rating = (TextView) v.findViewById(R.id.rating);
            imageView=(ImageView)v.findViewById(R.id.movie_image);
        }



    }

    public MovieAdapter(List<Movie> movies, int rowLayout, Context context)
    {
        this.movies = movies;
        this.rowLayout = rowLayout;
        this.context = context;
    }

    @Override
    public MovieAdapter.MovieViewHolder onCreateViewHolder(ViewGroup parent,
                                                            int viewType)
    {
        View view = LayoutInflater.from(parent.getContext()).inflate(rowLayout, parent, false);
        return new MovieViewHolder(view);
    }


    @Override
    public void onBindViewHolder(MovieViewHolder holder, final int position)
    {
        Movie movie= movies.get(position);
        holder.movieTitle.setText(movies.get(position).getTitle());
        holder.data.setText(movies.get(position).getReleaseDate());
        holder.movieDescription.setText(movies.get(position).getOverview());
        holder.rating.setText(movies.get(position).getvote_average().toString());
        MovieImage(holder,movie);
        applyClickEvents(holder,position);


    }
    private void applyClickEvents(MovieViewHolder holder,final int position)
    {
        holder.moviesLayout.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                listener.onItemClicked(position);
            }
        });


    }


    private void MovieImage(MovieViewHolder holder,Movie movie)
    {
        String base_URL="https://image.tmdb.org/t/p/";
        String size_Image="w500";
        String file_Path=movie.getPosterPath();

        StringBuilder image_Path=new StringBuilder();
        image_Path.append(base_URL).append(size_Image).append(file_Path);
        Log.d(TAG,"movie genere ids  "+movie.getGenreIds());
        Log.d(TAG,"movie relese date   "+movie.getReleaseDate());




        if(!TextUtils.isEmpty(image_Path))
        {
            Glide.with(context).load(image_Path.toString())
                    .thumbnail(0.5f)
                    .crossFade()
                    .transform(new CircleTransformation(context))
                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .into(holder.imageView);
        }
        else
        {
            holder.imageView.setImageResource(R.drawable.circle);
        }

    }

    public interface MovieAdapterListener
    {
        void onItemClicked(int position);

    }


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

MainActivity.java in which I am implenting the interface and overriding the method which I have declared in the interface.

package com.example.vikas.movie.activity;

import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.widget.Toast;


import com.example.vikas.movie.R;
import com.example.vikas.movie.adapter.MovieAdapter;
import com.example.vikas.movie.model.Movie;
import com.example.vikas.movie.model.MoviesResponse;
import com.example.vikas.movie.rest.ApiClient;
import com.example.vikas.movie.rest.ApiInterface;

import java.util.ArrayList;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends AppCompatActivity implements MovieAdapter.MovieAdapterListener
{

    private static final String TAG=MainActivity.class.getSimpleName();
    //get which got from web API
    private final static String API_KEY="xxxxx";
    private CoordinatorLayout coordinatorLayout;
   // private MovieAdapter movieAdapter;
    private RecyclerView recyclerView;
    private List<Movie> movieList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        coordinatorLayout=(CoordinatorLayout)findViewById(R.id.coordinate_layout);

        if(API_KEY.isEmpty())
        {
            Snackbar snackbar = Snackbar
                    .make(coordinatorLayout, "Please Enter The key", Snackbar.LENGTH_LONG);

            snackbar.show();
            return;
        }
        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
        recyclerView.setItemAnimator(new DefaultItemAnimator());



        ApiInterface apiInterface= ApiClient.getClient().create(ApiInterface.class);
        Call<MoviesResponse> call= apiInterface.getNowPlayingMovies(API_KEY);
        call.enqueue(new Callback<MoviesResponse>()
        {
            @Override
            public void onResponse(Call<MoviesResponse> call, Response<MoviesResponse> response)
            {

                 movieList= response.body().getResults();
                Log.d(TAG, "Number of movies received: " + movieList.size());
                recyclerView.setAdapter(new MovieAdapter(movieList, R.layout.recyclerview_item_movie, getApplicationContext()));
                // movieAdapter.notifyDataSetChanged();
               // Log.d(TAG, "Number of movies received: " + movieList.);


            }

            @Override
            public void onFailure(Call<MoviesResponse> call, Throwable t)
            {
                Snackbar snackbar = Snackbar
                        .make(coordinatorLayout, "Please Check your Internet Connection", Snackbar.LENGTH_LONG);

                snackbar.show();
                Log.e(TAG, t.toString());

            }
        });

    }

    @Override
    public void onItemClicked(int position)
    {
       Movie movie = movieList.get(position);
        movie.getGenreIds();
        movie.getId();
        Toast.makeText(getApplicationContext(), "id: "+ movie.getId(), Toast.LENGTH_SHORT).show();
    }


}

I am getting logcat like this

FATAL EXCEPTION: main
                                                                         Process: com.example.vikas.movie, PID: 23565
                                                                         java.lang.NullPointerException: Attempt to invoke interface method 'void com.example.vikas.movie.adapter.MovieAdapter$MovieAdapterListener.onItemClicked(int)' on a null object reference
                                                                             at com.example.vikas.movie.adapter.MovieAdapter$1.onClick(MovieAdapter.java:97)
                                                                             at android.view.View.performClick(View.java:5205)
                                                                             at android.view.View$PerformClick.run(View.java:21164)
                                                                             at android.os.Handler.handleCallback(Handler.java:739)
                                                                             at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                             at android.os.Looper.loop(Looper.java:148)
                                                                             at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
04-26 23:56:00.538 23565-23565/com.example.vikas.movie I/Process: Sending signal. PID: 23565 SIG: 9

Anyone please help I am not able to understand the problem.

rafsanahmad007
  • 23,683
  • 6
  • 47
  • 62
Vikas
  • 49
  • 9

3 Answers3

2

This happens because you haven't initialized "listener". You have to pass the listener when you create create new MovieAdapter in MainActivity and assign it to "listener".

In MovieAdapter.java, change public MovieAdapter() into

public MovieAdapter(List<Movie> movies, int rowLayout, Context context, MovieAdapterListener listener)
{
    this.movies = movies;
    this.rowLayout = rowLayout;
    this.context = context;
    this.listener=listener;
}

and in MainActivity.java, change the line

recyclerView.setAdapter(new MovieAdapter(movieList, R.layout.recyclerview_item_movie, getApplicationContext()));

into

recyclerView.setAdapter(new MovieAdapter(movieList, R.layout.recyclerview_item_movie, getApplicationContext(),listener));
//change "listener into the name of MovieAdapterListener object"
Bertram Gilfoyle
  • 9,899
  • 6
  • 42
  • 67
1

You get NullPointerException in your interface listener.

Initialize your interface listener in your Adapter class:

 public MovieAdapter(List<Movie> movies, int rowLayout, Context context) {
    this.movies = movies;
    this.rowLayout = rowLayout;
    this.context = context;
    listener = (MovieAdapterListener) context;  //add this

}

EDIT

Also now set the adapter using:

recyclerView.setAdapter(new MovieAdapter(movieList, R.layout.recyclerview_item_movie, MainActivity.this));
rafsanahmad007
  • 23,683
  • 6
  • 47
  • 62
  • I am getting this exception now after changes I have done you have suggested java.lang.ClassCastException: android.app.Application cannot be cast to com.example.vikas.movie.adapter.MovieAdapter$MovieAdapterListener at com.example.vikas.movie.adapter.MovieAdapter.(MovieAdapter.java:66) at com.example.vikas.movie.activity.MainActivity$1.onResponse(MainActivity.java:70) – Vikas Apr 26 '17 at 19:32
  • i have edited my answer.... – rafsanahmad007 Apr 26 '17 at 19:34
  • Thanks a lot you saved my day – Vikas Apr 26 '17 at 19:41
1

I believe the MovieAdapter should initialize the listener member:

public MovieAdapter(List<Movie> movies, int rowLayout, Context context, MovieAdapterListener lstn)
{
    this.movies = movies;
    this.rowLayout = rowLayout;
    this.context = context;
    this.listener = lstn;
}

And in MainActivity you should pass another instance of it when you're setting the adapter, since it implementing MovieAdapter.MovieAdapterListener:

recyclerView.setAdapter(new MovieAdapter(movieList, R.layout.recyclerview_item_movie, this, this));