Home > Back-end >  RecyclerView and OnItemClick: No value passed for parameter 'click' in Fragment
RecyclerView and OnItemClick: No value passed for parameter 'click' in Fragment

Time:06-22

I'm trying to implement an OnClick listener for specific items in a recyclerview. I've done it before with activities, but now I want to do this in a fragment and I've run into a problem. I'm getting the error No value passed for parameter 'click'. This is the line of code that gives that error:

recyclerAdapterAbstract = abstractList.let {AbstractAdapter(requireActivity(),it)}

This the only error Android Studio is currently showing me. The logcat doesn't show any error. Only the Build Output shows what's wrong and it's exactly what I said earlier

Fragment Class

  @Suppress("UNREACHABLE_CODE")
class AbstractWallpapers: Fragment(), PurchasesUpdatedListener, AbstractAdapter.OnItemClickListenerAbstract {

    private lateinit var subscribeAbstract: Button

    private var billingClient: BillingClient? = null

    lateinit var recyclerView: RecyclerView
    lateinit var abstractList: ArrayList<Abstract>

    private var recyclerAdapterAbstract: AbstractAdapter? = null
    private var myRef3: DatabaseReference? = null


    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_abstract_wallpaper, container, false)

        recyclerView = requireActivity().findViewById(R.id.abstract_recyclerView)


    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        recyclerView = view.findViewById(R.id.abstract_recyclerView)

        val layoutManager = GridLayoutManager(requireContext(), 2)

        recyclerView.layoutManager = layoutManager
        recyclerView.setHasFixedSize(true)

        myRef3 = FirebaseDatabase.getInstance().reference
        abstractList = ArrayList()
        ClearAll()
        GetDataFromFirebase()

        subscribeAbstract = view.findViewById(R.id.abstract_subscribe_btn)

        subscribeAbstract.setOnClickListener {
            subscribeAbstract()

        }

        //Establish connection to billing client
        //check subscription status from google play store cache
        //to check if item is already Subscribed or subscription is not renewed and cancelled
        billingClient = BillingClient.newBuilder(requireActivity()).enablePendingPurchases().setListener(this).build()
        billingClient!!.startConnection(object : BillingClientStateListener {

            override fun onBillingSetupFinished(billingResult: BillingResult) {
                if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                    val queryPurchase = billingClient!!.queryPurchases(BillingClient.SkuType.SUBS)

                    val queryPurchases = queryPurchase.purchasesList
                    if (queryPurchases != null && queryPurchases.size > 0) {
                        handlePurchases(queryPurchases)

                    } else {

                        saveSubscribeValueToPref(false)
                    }
                }
            }

            override fun onBillingServiceDisconnected() {
                Toast.makeText(requireActivity(), "Service Disconnected", Toast.LENGTH_SHORT).show()
            }
        })

        //item subscribed
        if (subscribeValueFromPref) {
            subscribeAbstract.visibility = View.GONE

        } else {
            subscribeAbstract.visibility = View.VISIBLE

        }
    }

    // Code relating to my Firebase storage
    @SuppressLint("NotifyDataSetChanged")
    private fun GetDataFromFirebase() {

        val query: Query = myRef3!!.child("Abstract")

        query.addListenerForSingleValueEvent(object : ValueEventListener {
            override fun onDataChange(snapshot: DataSnapshot) {

                for (dataSnapshot: DataSnapshot in snapshot.children) {
                    val abstract = Abstract()

                    abstract.abstract = dataSnapshot.child("abstract").value.toString()
                    abstractList.add(abstract)}

                recyclerAdapterAbstract = abstractList.let {AbstractAdapter(requireActivity(),it)}

                recyclerView.adapter = recyclerAdapterAbstract
                recyclerAdapterAbstract!!.notifyDataSetChanged()
            }

            override fun onCancelled(error: DatabaseError) {}
        })
        if (recyclerAdapterAbstract != null) recyclerAdapterAbstract!!.notifyDataSetChanged()
    }

    private fun ClearAll() {
        abstractList.clear()
        abstractList = ArrayList()
    }


    private val preferenceObject: SharedPreferences
        get() = requireActivity().getSharedPreferences(PREF_FILE, 0)

    private val preferenceEditObject: SharedPreferences.Editor
        get() {
            val pref = requireActivity().getSharedPreferences(PREF_FILE, 0)
            return pref.edit()
        }

    private val subscribeValueFromPref: Boolean
        get() = preferenceObject.getBoolean(SUBSCRIBE_KEY, false)

    private fun saveSubscribeValueToPref(value: Boolean) {
        preferenceEditObject.putBoolean(SUBSCRIBE_KEY, value).commit()
    }

    //initiate purchase on button click
    fun subscribeAbstract() {
        //check if service is already connected
        if (billingClient!!.isReady) {
            initiatePurchase()
        } else {
            billingClient = BillingClient.newBuilder(requireActivity()).enablePendingPurchases().setListener(this).build()
            billingClient!!.startConnection(object : BillingClientStateListener {
                override fun onBillingSetupFinished(billingResult: BillingResult) {
                    if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                        initiatePurchase()
                    } else {
                        Toast.makeText(requireActivity(), "Error "   billingResult.debugMessage, Toast.LENGTH_SHORT).show()
                    }
                }

                override fun onBillingServiceDisconnected() {
                    Toast.makeText(requireActivity(), "Service Disconnected ", Toast.LENGTH_SHORT).show()
                }
            })
        }
    }

    private fun initiatePurchase() {
        val skuList: MutableList<String> = ArrayList()
        skuList.add(ITEM_SKU_SUBSCRIBE)
        val params = SkuDetailsParams.newBuilder()
        params.setSkusList(skuList).setType(BillingClient.SkuType.SUBS)
        val billingResult = billingClient!!.isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS)
        if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
            billingClient!!.querySkuDetailsAsync(params.build()
            ) { billingResult, skuDetailsList ->
                if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                    if (skuDetailsList != null && skuDetailsList.size > 0) {
                        val flowParams = BillingFlowParams.newBuilder()
                            .setSkuDetails(skuDetailsList[0])
                            .build()
                        billingClient!!.launchBillingFlow(requireActivity(), flowParams)
                    } else {
                        //try to add subscription item "sub_example" in google play console
                        Toast.makeText(requireActivity(), "Item not Found", Toast.LENGTH_SHORT).show()
                    }
                } else {
                    Toast.makeText(requireActivity(),
                        " Error "   billingResult.debugMessage, Toast.LENGTH_SHORT).show()
                }
            }
        } else {
            Toast.makeText(requireActivity(),
                "Sorry Subscription not Supported. Please Update Play Store", Toast.LENGTH_SHORT).show()
        }
    }

    override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
        //if item subscribed
        if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
            handlePurchases(purchases)
        }
        else if (billingResult.responseCode == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
            val queryAlreadyPurchasesResult = billingClient!!.queryPurchases(BillingClient.SkuType.SUBS)
            val alreadyPurchases = queryAlreadyPurchasesResult.purchasesList
            alreadyPurchases?.let { handlePurchases(it) }
        }
        else if (billingResult.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
            Toast.makeText(requireActivity(), "Purchase Canceled", Toast.LENGTH_SHORT).show()
        }
        else {
            Toast.makeText(requireActivity(), "Error "   billingResult.debugMessage, Toast.LENGTH_SHORT).show()
        }
    }

    fun handlePurchases(purchases: List<Purchase>) {
        for (purchase in purchases) {
            //if item is purchased
            if (ITEM_SKU_SUBSCRIBE == purchase.sku && purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
                if (!verifyValidSignature(purchase.originalJson, purchase.signature)) {
                    // Invalid purchase
                    // show error to user
                    Toast.makeText(requireActivity(), "Error : invalid Purchase", Toast.LENGTH_SHORT).show()
                    return
                }
                // else purchase is valid
                //if item is purchased and not acknowledged
                if (!purchase.isAcknowledged) {
                    val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
                        .setPurchaseToken(purchase.purchaseToken)
                        .build()
                    billingClient!!.acknowledgePurchase(acknowledgePurchaseParams, ackPurchase)
                } else {
                    // Grant entitlement to the user on item purchase
                    // restart activity
                    if (!subscribeValueFromPref) {
                        saveSubscribeValueToPref(true)
                        Toast.makeText(requireActivity(), "Item Purchased", Toast.LENGTH_SHORT).show()
                        recreate(requireActivity())
                    }
                }
            } else if (ITEM_SKU_SUBSCRIBE == purchase.sku && purchase.purchaseState == Purchase.PurchaseState.PENDING) {
                Toast.makeText(requireActivity(),
                    "Purchase is Pending. Please complete Transaction", Toast.LENGTH_SHORT).show()
            } else if (ITEM_SKU_SUBSCRIBE == purchase.sku && purchase.purchaseState == Purchase.PurchaseState.UNSPECIFIED_STATE) {
                saveSubscribeValueToPref(false)
                subscribeAbstract.visibility = View.VISIBLE
                Toast.makeText(requireActivity(), "Purchase Status Unknown", Toast.LENGTH_SHORT).show()
            }
        }
    }

    var ackPurchase = AcknowledgePurchaseResponseListener { billingResult ->
        if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
            //if purchase is acknowledged
            // Grant entitlement to the user. and restart activity
            saveSubscribeValueToPref(true)
            recreate(requireActivity())
        }
    }

    /**
     * Verifies that the purchase was signed correctly for this developer's public key.
     *
     * Note: It's strongly recommended to perform such check on your backend since hackers can
     * replace this method with "constant true" if they decompile/rebuild your app.
     *
     */
    private fun verifyValidSignature(signedData: String, signature: String): Boolean {
        return try {
            // To get key go to Developer Console > Select your app > Development Tools > Services & APIs.
            val base64Key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhBlajrk5nNjpRTPJjDtGxgtgAeKijz3Wc0KrRKKSCxxsViHl7DhsI sUZfk4Y1jxSg4/3W1uRo/0UASM77XfJIq34bK9KYgoSAGYSuH8Z 4fK/MrPz7dHhsljkAi4GZkv8x9VhZdDdpn2GSHVFaxs8c HBOFp9aWAErHrQhi9/7fYf39pQSTC3WkVcy9xNDZxiiKTfDN3dyEvS0XQ617ZJwqDuRdkU5Aw9 R8r oXyURV/ekgCQkWfCUaTp/jWdySOIcR87Bde24lQAXbvJaL5uAYI4zPwO4sIP1AbXLuDtv3N2rFVmP/1cML/NHDcfI5FOoStz88jzJU26Ngpqu1QIDAQAB"
            Security.verifyPurchase(base64Key, signedData, signature)
        } catch (e: IOException) {
            false
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        if (billingClient != null) {
            billingClient!!.endConnection()
        }
    }

    companion object {
        const val PREF_FILE = "MyPref"
        const val SUBSCRIBE_KEY = "subscribe"
        const val ITEM_SKU_SUBSCRIBE = "abstract_wallpapers"
    }

    override fun onItemClick(item: String) {

    }
}

Adapter class

 class AbstractAdapter(private val mContext: Context, private val abstractList: ArrayList<Abstract>, private val click: OnItemClickListenerAbstract ) :
    RecyclerView.Adapter<AbstractAdapter.ViewHolder>() {

     interface OnItemClickListenerAbstract{
         fun onItemClick(item:String)
     }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.abstract_image_view, parent, false)
        return ViewHolder(view)

    }
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        Glide.with(mContext)
            .load(abstractList[position].abstract)
            .into(holder.imageView)

        holder.imageView.setOnClickListener {
            val intent = Intent(mContext, AbstractPreview::class.java)
            intent.putExtra("abstract", abstractList[position].abstract.toString())
            Toast.makeText(mContext, "Fullscreen view", Toast.LENGTH_SHORT).show()
            mContext.startActivity(intent)

        }

        holder.downloadBtn.setOnClickListener {
            abstractList.get(position).abstract?.let { it1 -> click.onItemClick(it1) }
        }
    }

    override fun getItemCount(): Int {
        return abstractList.size
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val imageView: ImageView = itemView.findViewById(R.id.abstractImageView)
        val downloadBtn: Button = itemView.findViewById(R.id.abstractDownloadBtn)

    }

    companion object
}

CodePudding user response:

You have 3 parameters for the class AbstractAdapter

 class AbstractAdapter(private val mContext: Context, private val abstractList: ArrayList<Abstract>, private val click: OnItemClickListenerAbstract ) 

but you are instantiating the object with only two parameters

AbstractAdapter(requireActivity(),it)

It's expecting the third parameter for the clickListener

AbstractAdapter(requireActivity(),it,this)

(send the Fragment as the third param)

  • Related