Search code examples
androidandroid-recyclerviewfastadapter

FastAdapter Click listeners for views inside item


I am trying to Implement a Click Listener for a Button Inside my CardView. The Item will be Deleted when I press this Button. But I can't find a way to implement it. The FastAdapter documentation is in Kotlin so there is no Java example.

Generally that is done in onBindView but for FastAdapter the approach is different. here is my Model(RequestBuyer)

Model.java



import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.google.gson.annotations.SerializedName;
import com.kazi.amarhut.R;
import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter;
import com.mikepenz.fastadapter.items.AbstractItem;
import com.mikepenz.fastadapter.listeners.OnClickListener;

import java.util.List;

public class RequestBuyer extends AbstractItem<RequestBuyer, RequestBuyer.ViewHolder> {

    @SerializedName("cropAmount")
    private double cropAmount;

    @SerializedName("buyerPhone")
    private String buyerPhone;

    @SerializedName("cropPrice")
    private double cropPrice;

    @SerializedName("sellerPhone")
    private String sellerPhone;

    @SerializedName("__v")
    private int V;

    @SerializedName("cropName")
    private String cropName;

    @SerializedName("_id")
    private String id;

    @SerializedName("postID")
    private String postID;

    @SerializedName("deliveryDate")
    private String deliveryDate;

    @SerializedName("status")
    private String status;

    FastItemAdapter<RequestBuyer> fastItemAdapter = new FastItemAdapter<>();

    public void setCropAmount(int cropAmount){
        this.cropAmount = cropAmount;
    }

    public double getCropAmount(){
        return cropAmount;
    }

    public void setBuyerPhone(String buyerPhone){
        this.buyerPhone = buyerPhone;
    }

    public String getBuyerPhone(){
        return buyerPhone;
    }

    public void setCropPrice(int cropPrice){
        this.cropPrice = cropPrice;
    }

    public double getCropPrice(){
        return cropPrice;
    }

    public void setSellerPhone(String sellerPhone){
        this.sellerPhone = sellerPhone;
    }

    public String getSellerPhone(){
        return sellerPhone;
    }

    public void setV(int V){
        this.V = V;
    }

    public int getV(){
        return V;
    }

    public void setCropName(String cropName){
        this.cropName = cropName;
    }

    public String getCropName(){
        return cropName;
    }

    public void setId(String id){
        this.id = id;
    }

    public String getId(){
        return id;
    }

    public void setPostID(String postID){
        this.postID = postID;
    }

    public String getPostID(){
        return postID;
    }

    public void setDeliveryDate(String deliveryDate){
        this.deliveryDate = deliveryDate;
    }

    public String getDeliveryDate(){
        return deliveryDate;
    }

    public void setStatus(String status){
        this.status = status;
    }

    public String getStatus(){
        return status;
    }

    @Override
    public String toString(){
        return
                "Response{" +
                        "cropAmount = '" + cropAmount + '\'' +
                        ",buyerPhone = '" + buyerPhone + '\'' +
                        ",cropPrice = '" + cropPrice + '\'' +
                        ",sellerPhone = '" + sellerPhone + '\'' +
                        ",__v = '" + V + '\'' +
                        ",cropName = '" + cropName + '\'' +
                        ",_id = '" + id + '\'' +
                        ",postID = '" + postID + '\'' +
                        ",deliveryDate = '" + deliveryDate + '\'' +
                        ",status = '" + status + '\'' +
                        "}";
    }

    @Override
    public int getLayoutRes() {
        return R.layout.activity_request_cardview;
    }

    @Override
    public int getType() {
        return R.id.activity_request_card;
    }

    @Override
    public void bindView(final RequestBuyer.ViewHolder holder, List payloads) {
        super.bindView(holder,payloads);

        holder.tvCropName.setText(cropName);
        holder.tvCropPrice.setText(String.valueOf(cropPrice) + " tk/kg");
        holder.tvCropAmount.setText(String.valueOf(cropAmount) + " kg");

        String rawDate = deliveryDate;
        int index = rawDate.indexOf("T");
        String date = rawDate.substring(0,index);
        holder.tvDeliveryDate.setText("Delivery Date: " + date);

        holder.tvBuyerPhone.setText("Buyer : "+ buyerPhone);
        holder.tvSellerPhone.setText("Seller : "+ sellerPhone);

        holder.tvReqStatus.setText("Status : " + status);

        holder.btnReqAccept.setVisibility(View.GONE);

        holder.btnReqReject.setText("Delete");

        holder.btnReqReject.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
    }

    //Reset the view here (this is an optional method, but recommended)
    @Override
    public void unbindView(RequestBuyer.ViewHolder holder) {
        super.unbindView(holder);

    }

    @NonNull
    @Override
    public RequestBuyer.ViewHolder getViewHolder(View v) {
        return new RequestBuyer.ViewHolder(v);
    }

    public  static class ViewHolder extends RecyclerView.ViewHolder {

        TextView tvCropName,tvCropPrice,tvCropAmount,tvDeliveryDate,tvReqStatus, tvBuyerPhone, tvSellerPhone;

        Button btnReqAccept, btnReqReject;

        public ViewHolder(View itemView) {
            super(itemView);

            tvCropAmount = itemView.findViewById(R.id.activity_request_cardview_tv_cropAmount);
            tvCropPrice = itemView.findViewById(R.id.activity_request_cardview_tv_cropPrice);
            tvCropName = itemView.findViewById(R.id.activity_request_cardview_tv_cropName);
            tvDeliveryDate = itemView.findViewById(R.id.activity_request_cardview_tv_cropDeliveryDate);
            tvReqStatus = itemView.findViewById(R.id.activity_request_cardview_tv_reqStatus);
            tvBuyerPhone = itemView.findViewById(R.id.activity_request_cardview_tv_buyerPhone);
            tvSellerPhone = itemView.findViewById(R.id.activity_request_cardview_tv_sellerPhone);

            btnReqAccept = itemView.findViewById(R.id.activity_request_cardview_btn_reqAccept);

            btnReqReject = itemView.findViewById(R.id.activity_request_cardview_btn_reqReject);

        }
    }
}

Here is My Fragment Activity(RequestActivityBuyer)

Activity.java

package com.kazi.amarhut.CoreActivities.Buyer;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.androidnetworking.AndroidNetworking;
import com.androidnetworking.common.Priority;
import com.androidnetworking.error.ANError;
import com.androidnetworking.interfaces.JSONArrayRequestListener;
import com.google.gson.Gson;
import com.kazi.amarhut.Models.RequestBuyer;
import com.kazi.amarhut.Models.RequestFarmer;
import com.kazi.amarhut.R;
import com.kazi.amarhut.Utils.ClickListenerHelper;
import com.kazi.amarhut.Utils.PrefManager;
import com.mikepenz.fastadapter.FastAdapter;
import com.mikepenz.fastadapter.IItem;
import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter;
import com.mikepenz.fastadapter.listeners.ClickEventHook;
import com.mikepenz.fastadapter.listeners.EventHook;
import com.mikepenz.fastadapter.listeners.OnCreateViewHolderListener;

import org.json.JSONArray;
import org.json.JSONException;

import java.util.ArrayList;
import java.util.List;

public class RequestActivityBuyer extends Fragment {

    FastItemAdapter<RequestBuyer>fastAdapter;
    RecyclerView recyclerView;
    List<RequestBuyer> requestBuyerList = new ArrayList<>();

    ClickListenerHelper<RequestBuyer> clickListenerHelper;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.activity_buyer_request,container,false);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        jsonRequest();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        recyclerView = view.findViewById(R.id.activity_buyer_request_recyclerView);

        setuprecyclerview();
    }


    private void jsonRequest() {

        String buyerPhone = new PrefManager(getContext()).getUserInfo().get("phone");

        AndroidNetworking.get("https://obscure-stream-72200.herokuapp.com/api/requests/findBy/buyerPhone/"+buyerPhone)
                .setPriority(Priority.MEDIUM)
                .build()
                .getAsJSONArray(new JSONArrayRequestListener() {
                    @Override
                    public void onResponse(JSONArray response) {
                        // do anything with response

                        Gson gson = new Gson();
                        RequestBuyer requestBuyerObject;

                        for (int i = 0; i < response.length(); i++) {
                            try {

                                requestBuyerObject = gson.fromJson(response.get(i).toString(), RequestBuyer.class);
                                requestBuyerList.add(requestBuyerObject);

                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        }
                        if (!(requestBuyerList.isEmpty())) fastAdapter.add(requestBuyerList);
                    }
                    @Override
                    public void onError(ANError error) {
                        if (error.getErrorCode() != 0) {
                            // received error from server
                            // error.getErrorCode() - the error code from server
                            // error.getErrorBody() - the error body from server
                            // error.getErrorDetail() - just an error detail
                            Log.d("Error", "onError errorCode : " + error.getErrorCode());
                            Log.d("Error", "onError errorBody : " + error.getErrorBody());
                            Log.d("Error", "onError errorDetail : " + error.getErrorDetail());

                        } else {
                            // error.getErrorDetail() : connectionError, parseError, requestCancelledError
                            Log.d("Error", "onError errorDetail : " + error.getErrorDetail());
                        }
                    }
                });
    }


    private void setuprecyclerview() {

        fastAdapter = new FastItemAdapter<RequestBuyer>();
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
        recyclerView.setAdapter(fastAdapter);



    }

}

I tried to follow this example but it's not working as the library changed gradually since then. Link : FastAdpter ViewHolder Listener


Solution

  • The FastAdapter Library tries to ensure listeners are implemented in the most efficient way possible. Reusing listeners and not re-creating them over and over again. It also tries to limit the potential of leaks.

    To do this the FastAdapter comes with a set of existing Hooks into your RecyclerView items.

    A simple ClickListener to a item specific view can be done like this:

    //just add an `EventHook` to your `FastAdapter` by implementing either a `ClickEventHook`, `LongClickEventHook`, `TouchEventHook`, `CustomEventHook`
    fastAdapter.addEventHook(object : ClickEventHook<SimpleImageItem>() {
        override fun onBind(viewHolder: RecyclerView.ViewHolder): View? {
            //return the views on which you want to bind this event
            return if (viewHolder is SimpleImageItem.ViewHolder) {
                viewHolder.viewWhichReactsOnClick
            } else null
        }
    
        override fun onClick(v: View, position: Int, fastAdapter: FastAdapter<SimpleImageItem>, item: SimpleImageItem) {
            //react on the click event
        }
    })
    

    There are additional hooks for LongClicks, TouchEvents and a generic interface to implement your own custom hooks.

    Starting with v4.1.0 the whole boilerplate can be simplified to:

    adapter.addClickListener({ vh: SimpleImageItem.ViewHolder -> vh.viewWhichReactsOnClick }) { _, position, _: FastAdapter<SimpleImageItem>, item: SimpleImageItem ->
                //react on the click event
    }
    

    Source references: