我知道这个问题非常多,但我经常被搜查,我无法理解这个问题。我正在创建一个接口,用于处理回收站视图上特定项目的点击侦听器
这是我的课程
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
任何人请帮助我无法理解这个问题。
答案 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));