Search code examples
androidkotlinandroid-activitybuilder

Android - How to pass a function to an Activity?


I am attempting to create a Builder for an activity. The reason is because this activity can be started many different ways. I created a Builder class like this:

class ActivityBuilder {

    private var showToolBar = false
    private var postExecutable: (() -> Unit)? = null

    fun showToolbar(boolean: Boolean) : ActivityBuilder {
        this.showToolBar = boolean
        return this
    }

    fun setPostExecutable(function: () -> Unit) : ActivityBuilder {
        this.postExecute = function
        return this
    }

    fun start(context: Context){
        val intent = Intent(context, Activity::class.java)
        context.startActivity(intent)
    }
}

The idea is to call something like this and have access to these fields inside of the activity.

 ActivityBuilder().showToolbar(false).setPostExecutable { { doSomething() } }.start(this)

I guess I could also use a companion object and that would serve the same purpose.

companion object Builder {

    private var showToolBar = false
    private var postExecute: (() -> Unit)? = null

    fun showToolbar(boolean: Boolean) : Builder {
        this.showToolBar = boolean
        return this
    }

    fun setPostExecutable(function: () -> Unit) : Builder {
        this.postExecute = function
        return this
    }

    fun start(context: Context){
        val intent = Intent(context, AuthActivity::class.java)
        context.startActivity(intent)
    }
}

The issue is coming mostly from the "postExecutable" field. I need to call the function at a certain point but it is not parcelable, so I cannot pass it through the intent when starting activity.

If anyone has a solution, I appreciate it!


Solution

  • This is one solution I found, may not be the most elegant. I created a broadcast receiver that I start at the same time as my activity using the parent context.

    class ActivityBuilder(private val context: Context) {
    
        private var postSuccessExecutable: (() -> Unit)? = null
        ...
        private fun setupReceiver(){
    
            val filter = IntentFilter()
            filter.addAction("SUCCESS")
    
            val receiver = object : BroadcastReceiver() {
                override fun onReceive(c: Context?, intent: Intent?) {
    
                    context.unregisterReceiver(this)
    
                    if (intent?.action == "SUCCESS"){
                        Toast.makeText(context, "Successful", Toast.LENGTH_SHORT).show()
                        postSuccessExecutable?.invoke()
                    }
                }
            }
    
            context.registerReceiver(authReceiver, filter)
        }
        ...
    }
    

    When I want to trigger the function, I just send a broadcast:

    private fun sendSuccessBroadcast(data: String){
        val intent = Intent()
        intent.action = "SUCCESS"
        intent.putExtra("data", String)
        requireContext().sendBroadcast(intent)
    }