I'm following approach from Jared Burrows from the post here: How to create interface between Fragment and adapter? Unfortunately I'm getting NPE at line interfacePostAdapter.textMessage(username); I understand that the issue is with interface initialization, but unfortunately I cannot find solution from all similar posts.
My Adapter
public class PostDataAdapter extends RecyclerView.Adapter<PostDataAdapter.ViewHolder> {
private ArrayList<PostData> arrayList;
private InterfacePostAdapter interfacePostAdapter;
public PostDataAdapter(ArrayList<PostData> arrayList, InterfacePostAdapter interfacePostAdapter) {
this.arrayList = arrayList;
this.interfacePostAdapter = interfacePostAdapter;
}
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_postdata_recyclerview,parent, false);
ViewHolder viewHolder = new ViewHolder(view,interfacePostAdapter);
return viewHolder;
}
public void onBindViewHolder(ViewHolder holder, int position) {
holder.name.setText(arrayList.get(position).getName());
}
public int getItemCount() {
return arrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView name;
ImageView userImg;
InterfacePostAdapter interfacePostAdapter;
public ViewHolder(View itemView, InterfacePostAdapter interfacePostAdapter) {
super(itemView);
name = itemView.findViewById(R.id.textView_name);
userImg = itemView.findViewById(R.id.imgView_userIcon);
this.interfacePostAdapter = interfacePostAdapter;
userImg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = getBindingAdapterPosition();
String username = arrayList.get(position).getName();
interfacePostAdapter.textMessage(username); // here is NullPointerException
}
});
}
}
public interface InterfacePostAdapter {
void textMessage (String username);
}
}
My Fragment
public class LoggedInFragment extends Fragment implements PostDataAdapter.InterfacePostAdapter {
private FragmentLoggedinBinding binding;
private PostDataAdapter postDataAdapter;
private PostDataViewModel postDataViewModel;
private RecyclerView recyclerView;
PostDataAdapter.InterfacePostAdapter interfacePostAdapter;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_loggedin, container, false);
View view = binding.getRoot();
recyclerView = binding.recyclerView;
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
postDataAdapter = new PostDataAdapter(postDataViewModel.getPostData().getValue(), interfacePostAdapter);
recyclerView.setAdapter(postDataAdapter);
return view;
}
@Override
public void textMessage(String username) {
Toast.makeText(getContext(),username, Toast.LENGTH_SHORT).show();
}
//This part should be not relevant to the interface issue
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
postDataViewModel = new ViewModelProvider(this).get(PostDataViewModel.class);
postDataViewModel.initPostData();
postDataViewModel.getPostData().observe(this, new Observer<ArrayList<PostData>>() {
@Override
public void onChanged(ArrayList<PostData> arrayList) {
postDataAdapter.notifyDataSetChanged();
}
});
}
}
You need to track your variable and make sure it's initialized properly. After doing that, I concluded that you haven't actually given a value to PostDataAdapter.InterfacePostAdapter interfacePostAdapter;
in your LoggedInFragment
anywhere. I do see that your fragment implements the said interface, so in that case you actually do not need the variable at all, just change that line this:
postDataAdapter = new PostDataAdapter(postDataViewModel.getPostData().getValue(), interfacePostAdapter);
to this:
postDataAdapter = new PostDataAdapter(postDataViewModel.getPostData().getValue(), this);
Your variable was not initialized anywhere, so you were basically passing null to your adapter. There's a couple of ways you can pass an interface, and you mixed two of them in a bad way - when the class implements that interface, you can pass the current instance using this
, or you could have used your variable but with proper initialization.