android – How to show fragment dialog in button.setOnClickListener from Adapter class in Kotlin-MVP?-ThrowExceptions

Exception or error:

I’m developing one Android application using this Kotlin-MVP structure. I have one activity and it contains TabLayout of 4 fragments. All fragment has one button in RecyclerView. I need to show one “Fragment Dialog” on that button click listener. Can you please let me know how can I show fragment dialog on button click listener from adapter class? Please review screenshot.

enter image description here

I’m accessing button on click listener event from Adapter class which is below itemView.btn_accept.setOnClickListener:

class InApprovalAdapter(private val jobListItems: MutableList<JobItem>) : RecyclerView.Adapter<InApprovalAdapter.JobViewHolder>() {

private var _ProfileId: Long? = null;

fun getProfileId(): Long? {
    return _ProfileId
}

fun setProfileId(s: Long) {
    _ProfileId = s
}

private var _UserToken : String? = null;

fun getUserToken(): String? {
    return _UserToken
}

fun setUserToken(s: String) {
    _UserToken = s
}

private var _UserTypeId : Long? = null;
fun getUserTypeId(): Long? {
    return _UserTypeId
}

fun setUserTypeId(s: Long) {
    _UserTypeId = s
}


override fun getItemCount() = this.jobListItems.size

override fun onBindViewHolder(holder: JobViewHolder, position: Int) = holder.let {
    it.clear()
    it.onBind(position)
}

override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int) = JobViewHolder(LayoutInflater.from(parent?.context)
        .inflate(R.layout.item_inapproval_list, parent, false))

internal fun addJobsToList(jobs: List<JobItem>, profileId: Long?, userToken: String?, userTypeId: Long?) {
    this.jobListItems.addAll(jobs)
    setProfileId(profileId!!.toLong())
    setUserToken(userToken!!)
    setUserTypeId(userTypeId!!)
    notifyDataSetChanged()
}

inner class JobViewHolder(view: View) : RecyclerView.ViewHolder(view) {

    fun clear() {
        itemView.tv_job_id.text = "";
        itemView.tv_job_title.text= "";
        //itemView.tv_job_description.text ="";
        itemView.tv_job_category.text ="";
        itemView.tv_date_created.text ="";
    }

    fun onBind(position: Int) {

        val (jobId, name, description, serviceId, serviceName,
                address, engineerIds, engineerNames, startDateTimeUtc,
                startDateTimeLocal, endDateTimeUtc, endDateTimeLocal,
                customerId, customerName, customerMobile, customerAltMobile,
                priorityTypeId, priorityTypeName, statusTypeId, statusTypeName,
                isDeleted, isStatusTypeActive, createdBy, createdByName,
                dateCreatedPretty, modifiedBy, modifiedByName ,hasJobMedia,
                jobMedias, hasJobFeedback, jobDetailsImage, dateCreatedUtc, dateModifiedUtc) = jobListItems[position]

        inflateData(jobId, name,
                description,
                serviceId,
                serviceName,
                address,
                engineerIds,
                engineerNames,
                startDateTimeUtc,
                startDateTimeLocal,
                endDateTimeUtc,
                endDateTimeLocal,
                customerId,
                customerName,
                customerMobile,
                customerAltMobile,
                priorityTypeId,priorityTypeName,
                statusTypeId,
                statusTypeName,
                isDeleted,
                isStatusTypeActive,
                createdBy,
                createdByName,
                dateCreatedPretty,
                modifiedBy,
                modifiedByName ,
                hasJobMedia,
                jobMedias, hasJobFeedback, jobDetailsImage, dateCreatedUtc, dateModifiedUtc)
        setItemClickListener(jobId)
    }

    private fun setItemClickListener(jobId: Long?) {
        itemView.setOnClickListener {
            jobId?.let {
                try {
                    val intent = Intent(itemView.context, ServiceDetailActivity::class.java)
                    intent.putExtra("JobId", jobId)
                    itemView.context.startActivity(intent)
                } catch (e: Exception) {
                    Toast.makeText(itemView.context, e.message, Toast.LENGTH_LONG).show()
                }
            }
        }

        itemView.btn_accept.setOnClickListener {



        }

        itemView.btn_reject.setOnClickListener{

        }
    }
    private fun inflateData(jobId: Long?, name: String?, description: String?, serviceId: Long?, serviceName: String?, address: String?, engineerIds: String?,
                            engineerNames: String?, startDateTimeUtc: String?, startDateTimeLocal: String?, endDateTimeUtc: String?,
                            endDateTimeLocal: String?, customerId: Long?, customerName: String?, customerMobile:String?, customerAltMobile: String?,
                            priorityTypeId: Long?, priorityTypeName: String?, statusTypeId: Long?, statusTypeName: String?, isDeleted: Boolean?, isStatusTypeActive: Boolean?,
                            createdBy: Long?, createdByName: String?, dateCreatedPretty: String?, modifiedBy: Long?, modifiedByName: String?, hasJobMedia: Boolean?,
                            jobMedias: List<JobDetailsImage>?, hasJobFeedback: Boolean?, jobDetailsImage:  List<JobDetailsImage>?, dateCreatedUtc: String?, dateModifiedUtc: String?) {
        name.let {
            itemView.tv_job_title.text = it;
        }
        jobId.let {
            itemView.tv_job_id.text = "Job\n#" + it
        }
        /*description.let {
            itemView.tv_job_description.text = it
        }*/
        serviceName.let {
            itemView.tv_job_category.text = it
        }
        dateCreatedPretty.let {
            itemView.tv_date_created.text = it
        }

        if(getUserTypeId() == AppConstants.UserType.Administrator.type ||
                getUserTypeId() == AppConstants.UserType.Admin.type)
        {
            itemView.btn_reject.text = "Reject";
        }
        else
        {
            itemView.btn_reject.text = "Delete";
            itemView.btn_accept.visibility = View.GONE
        }
    }

    private fun callJobStatusChangeApi(jobId: Long?, statusTypeId: Long?)
    {
        val androidId = Settings.Secure.getString(itemView.context.contentResolver, Settings.Secure.ANDROID_ID)

        Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_JOB_CHANGEJOBSTATUS)
                .addHeaders("Authorization", "bearer " + getUserToken())
                .addQueryParameter("profileId",  getProfileId().toString())
                .addQueryParameter("jobId", jobId.toString())
                .addQueryParameter("statusTypeId", statusTypeId.toString())
                .addQueryParameter("DeviceId", androidId.toString())
                .build()
                .getAsObject(BaseResponse::class.java, object : ParsedRequestListener<BaseResponse> {

                    override fun onResponse(baseResponse: BaseResponse) {
                        // do anything with response
                        println("succeeded : " + baseResponse.succeeded)
                        println("message : " + baseResponse.message)

                        if(baseResponse.succeeded)
                        {
                            val inApprovalFragment : InApprovalFragment = InApprovalFragment()
                            inApprovalFragment.showStatusSubmissionSuccessMessage(itemView.context, baseResponse.message);
                            notifyDataSetChanged();
                        }
                    }

                    override fun onError(anError: ANError) {
                        // handle error
                        println(anError.message);
                    }

                })
    }

}

}
How to solve:

If you have problems accessing the FragmentManager you can simply pass a lambda to your adapter as the accept button’s OnClickListener:

class InApprovalAdapter(
    private val jobListItems: MutableList<JobItem>
    // If you have data to pass to the handler(like a jobId for example) 
    // modify the lambda like (Int) -> Unit
    private val acceptHandler: () -> Unit
    ) : RecyclerView.Adapter<InApprovalAdapter.JobViewHolder>() {

Then you can use that lambda:

itemView.btn_accept.setOnClickListener {
     acceptHandler()
}

Then create the adapter:

val adapter = InApprovalAdapter(theListOfItems, val clickListener: (Item) -> Unit) {
    // I'm assuming you're creating this adapter inside the Fragment class
    // so at this point you can access getFragmentManager()
    // ideally you'll let the presenter know that something happened in the view: presenter.userAcceptedJob()
    // and the presenter will call back a method on the view to actually show the DialogFragment.
}

###

I does same thing , shown custom dialog from adapter which is called from fragment.Not need to make dialog fragment,it will do same thing.

Pass activity from fragment while setting adapter

in ListFragment:-

rvAdapter = Listadapter( listnotes,activity!!)

in Listadapter class :-

class Listadapter( val DataList: ArrayList<String>?,val parentActivity: Activity) : RecyclerView.Adapter<Listadapter.ViewHolder>() {}

in onBindViewHolder method:-

view.notes.setOnClickListener {
        DialogNOTES(parentActivity,DataList[position])
    }

make method to show custom dailog in Listadapter class:-

private fun DialogNOTES(parentActivity: Activity,notes:String) {
    val dialog = Dialog(parentActivity)
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
    dialog.setCancelable(true)
    dialog.setContentView(R.layout.notes_dilog)//custom dialog layout 
    dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

    dialog.show()

    dialog.dilog_notes.setText(notes)


}

Leave a Reply

Your email address will not be published. Required fields are marked *