minikate
minikate

Reputation: 305

Get Document ID from FirebaseRecyclerAdapter and pass value to new page

I have a FirestoreRecyclerAdapter which displays a list of documents. I have a button beside each item in the list. On clicking this button, I want to get the unique Id of the item that is chosen, and then take the user to a page displaying this item's individual details.

Essentially I want to pass the Id of the document clicked to the next page. However, my button is throwing a null pointer exception when clicked.

This code is from my ClubAdapter class.

public class ClubAdapter1 extends FirestoreRecyclerAdapter<Club, ClubAdapter1.ClubHolder> {

    private String clubId;
    private Context context;

    public ClubAdapter1(@NonNull FirestoreRecyclerOptions<Club> options) {
        super(options);
    }

    @Override
    protected void onBindViewHolder(@NonNull ClubHolder holder, int position, @NonNull Club model) {
        holder.lblName.setText(model.getClubName());
        //getting the ID of the particular event clicked
        clubId = getSnapshots().getSnapshot(position).getId();

        holder.btnDetails.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = new Intent(context, ViewSingleClub.class);
                i.putExtra("id", clubId);
                context.startActivity(i);
            }
        });
    }

    @NonNull
    @Override
    public ClubHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.clublist_layout, parent, false);
        return new ClubHolder(v);
    }

    class ClubHolder extends RecyclerView.ViewHolder {

        TextView lblName;
        Button btnDetails;

        public ClubHolder(@NonNull View itemView) {
            super(itemView);

            lblName = itemView.findViewById(R.id.lblName);
            btnDetails = itemView.findViewById(R.id.btnDetails);
        }
    }
}

I keep getting an error at the line Intent i = new Intent(context, ViewSingleClub.class); I think it could be something to do with my context variable referencing itself, but also unsure if I am getting the ID correctly. Can anyone help with this?

This is my error:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.marykate.marykatefordefyp, PID: 2718
    java.lang.NullPointerException
        at android.content.ComponentName.<init>(ComponentName.java:77)
        at android.content.Intent.<init>(Intent.java:3842)
        at com.example.marykate.marykatefordefyp.ClubAdapter1$1.onClick(ClubAdapter1.java:36)
        at android.view.View.performClick(View.java:4457)
        at android.view.View$PerformClick.run(View.java:18491)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5336)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:681)
        at dalvik.system.NativeStart.main(Native Method)

Upvotes: 1

Views: 375

Answers (2)

Alex Mamo
Alex Mamo

Reputation: 138824

To solve this, move the following lines of code inside onBindViewHolder() method like this:

holder.btnDetails.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent i = new Intent(context, ViewSingleClub.class);
        i.putExtra("id", clubId);
        context.startActivity(i);
    }
});

See, I added the click listener on holder.btnDetails.

Edit:

According to your comments, please also make the following operations. Change the constructor to:

public ClubAdapter1(@NonNull FirestoreRecyclerOptions<Club> options, Context context) {
    super(options);
    this.context = context;
}

And when you create an object of your adapter class inside the activity, pass also the context to the constructor.

Upvotes: 0

Prayag Gediya
Prayag Gediya

Reputation: 1118

this is because you are assigning "context with itself". pass context from class where you initialise your adapter.

suppose i have adapter with name "ClubAdapter" and calling class named "ClubClass"

in ClubClass :

ClubAdapter clubAdapter = new ClubAdapter(list, context);
// if you'r calling it from activity then pass "Activity.this" and if fragment then "getContext()" as context.
and in ClubAdapter

public class ClubAdapter extends RecyclerView.Adapter<ClubAdapter.ClubHolder> {
    private Context context;
    private List<String> list;
   

    public ClubAdapter(List<String> list, Context context) {
        this.list = list;
        this.context = context;
    }
    
    @NonNull
    @Override
    public ClubHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View itemView = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.item_sample, viewGroup, false);
        return new ClubHolder(itemView, context);
    }
    
    
    public class ClubHolder extends RecyclerView.ViewHolder {

        private Context context;

        private ClunHolder(@NonNull View itemView,Context context) {
            super(itemView);
            this.context = context;
           
        }
        }
}

or you can make interface like this.

public interface RecycleViewOnItemClickListener {
    void onItemClick(int position);
}

and pass it to your adapter from calling class.

suppose i have adapter with name "SampleAdapter" and calling class named "SampleClass" In "SampleClass" you can pass interface in Adapter as parameter.

SampleAdapter sampleAdapter = new SampleAdapter(list, new RecycleViewOnItemClickListener() {
            @Override
            public void onItemClick(int position) {
                // do what you want to perform
            }
        });

In "ClubAdapter"

public class ClubAdapter extends RecyclerView.Adapter<ClubAdapter.ClubHolder> {
        private RecycleViewOnItemClickListener recycleViewOnItemClickListener;
        private List<String> list;
       

        public ClubAdapter(List<String> list, RecycleViewOnItemClickListener recycleViewOnItemClickListener) {
            this.list = list;
            this.recycleViewOnItemClickListener = recycleViewOnItemClickListener;
        }
        
        @NonNull
        @Override
        public ClubHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
            View itemView = LayoutInflater.from(viewGroup.getContext())
                    .inflate(R.layout.item_sample, viewGroup, false);
            return new ClubHolder(itemView, recycleViewOnItemClickListener);
        }
        
        
        public class ClubHolder extends RecyclerView.ViewHolder {

            private RecycleViewOnItemClickListener recycleViewOnItemClickListener;

            private ClunHolder(@NonNull View itemView,RecycleViewOnItemClickListener recycleViewOnItemClickListener) {
                super(itemView);
                this.recycleViewOnItemClickListener = recycleViewOnItemClickListener;
               //you can callback onItemClick method from here on button click event so it give callback in "ClubActivity".
               btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    recycleViewOnItemClickListener.onItemClick(getAdapterPosition());
                }
            });
            }
            }
            }

Upvotes: 1

Related Questions