在回收器项单击侦听器界面中获取空指针异常

时间:2017-04-26 18:39:28

标签: java android nullpointerexception android-recyclerview

我知道这个问题非常多,但我经常被搜查,我无法理解这个问题。我正在创建一个接口,用于处理回收站视图上特定项目的点击侦听器

这是我的课程

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,我在其中实现接口并覆盖我在接口中声明的方法。

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


}

我正在获得像这样的logcat

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

任何人请帮助我无法理解这个问题。

3 个答案:

答案 0 :(得分:2)

这是因为您尚未初始化“侦听器”。您必须在MainActivity中创建新的MovieAdapter时传递侦听器并将其分配给“侦听器”。

MovieAdapter.java 中,将公共MovieAdapter()更改为

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

并在MainActivity.java中, 改变行

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

recyclerView.setAdapter(new MovieAdapter(movieList, R.layout.recyclerview_item_movie, getApplicationContext(),listener));
//change "listener into the name of MovieAdapterListener object"

答案 1 :(得分:1)

您的界面侦听器中获得NullPointerException

在Adapter类中初始化接口侦听器:

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

}

修改

现在也使用以下方式设置适配器:

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

答案 2 :(得分:1)

我相信MovieAdapter应初始化侦听器成员:

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

在MainActivity中,当你设置适配器时,你应该传递它的另一个实例,因为它实现了MovieAdapter.MovieAdapterListener:

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