通过调用 RecyclerView Adapter 和 Fragment 之间的接口导致空指针异常 说明:

问题描述

我遵循 Jared Burrows 的方法从这里的帖子:How to create interface between Fragment and adapter? 不幸的是,我在 line interfacePostAdapter.textMessage(username); 处获得了 NPE;我知道问题出在接口初始化上,但不幸的是我无法从所有类似的帖子中找到解决方案。

我的适配器

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

我的片段

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

解决方法

您需要跟踪您的变量并确保它已正确初始化。这样做之后,我得出结论,您实际上并没有在 PostDataAdapter.InterfacePostAdapter interfacePostAdapter; 的任何地方为 LoggedInFragment 赋值。我确实看到您的片段实现了上述接口,因此在这种情况下,您实际上根本不需要变量,只需将该行更改为:

postDataAdapter = new PostDataAdapter(postDataViewModel.getPostData().getValue(),interfacePostAdapter);

为此:

postDataAdapter = new PostDataAdapter(postDataViewModel.getPostData().getValue(),this);

说明:

您的变量未在任何地方初始化,因此您基本上是将 null 传递给您的适配器。有几种方法可以传递接口,但您以一种糟糕的方式混合了其中的两种方法 - 当类实现该接口时,您可以使用 this 传递当前实例,或者您可以使用变量但是适当的初始化。