Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin - passing function as parameter via Intent

I have this function in kotlin extension file to pass method but it doesn't work. Please explain me how it make correctly, I try this:

fun showErrorClientScreen(context: Context, action : () -> Unit) {
    val intent = Intent(context, RestClientErrorActivity::class.java)

    val bundle = Bundle()
    bundle.putSerializable(UPDATE_CLIENT_ERROR, ErrorClientListener {  action })
    intent.putExtra(UPDATE_CLIENT_ERROR_BUNDLE, bundle)

    context.startActivity(intent)
}

use java interface

public interface ErrorClientListener extends Serializable {

    void tryAgainFunction();

}

and my activity where i need listen click button and try again send request:

class RestClientErrorActivity: BaseActivity(), View.OnClickListener {

    private lateinit var errorClientListener: ErrorClientListener

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_rest_client_error)

        try {
            val bundle = intent.getBundleExtra(UPDATE_CLIENT_ERROR_BUNDLE)
            errorClientListener = bundle?.getSerializable(UPDATE_CLIENT_ERROR) as ErrorClientListener
        } catch (e: Exception) {
            e.message
        }
    }

    override fun onClick(v: View?) {
        when (v?.id) {
            R.id.ib_update -> errorClientListener.tryAgainFunction()
        }
    }

}
like image 483
nicolas asinovich Avatar asked Jun 20 '18 12:06

nicolas asinovich


People also ask

Can you pass functions as parameters in Kotlin?

In Kotlin, a function which can accept a function as parameter or can return a function is called Higher-Order function. Instead of Integer, String or Array as a parameter to function, we will pass anonymous function or lambdas. Frequently, lambdas are passed as parameter in Kotlin functions for the convenience.

What is the putExtra () method used with intent for?

putExtra() method is used for sending the data, data in key-value pair key is variable name and value can be Int, String, Float, etc. getStringExtra() method is for getting the data(key) that is sent by the above method.

Can Kotlin pass by reference?

Since no assignment is possible for function parameters, the main advantage of passing by reference in C++ does not exist in Kotlin. If the object (passed to the function) has a method which changes its internal state, it will affect the original object. No copy is ever generated when passing objects to functions.

How do you pass an object as parameter in Kotlin?

The simplest answer is to have your objects all implement the same interface, e.g.: interface Language { val ZERO: String val ONE: String } internal object A: Language { override val ZERO = "ZERO" override val ONE = "ONE" } // …


1 Answers

It is quite strange to package interfaces between activities and it is definitely not advisable. One reason why it is maybe not serializing between Activity A and Activity B is because the object was created in Activity A, it is treated as anonymous class creation and Activity A holds the reference to this object, hence preventing it from being serialised. This is good, because you can create references to objects within the interface callback whose reference in turn would be held by class instantiating it. Therefore, garbage collector won't be able to run collections on these objects and free up the space; causing a massive memory leak.

The alternative approach to your problem could be using clean architectures and a Singleton class pattern that is accessible by both activities and instantiated only once by say Activity A:

class SingletonErrorHandler private constructor(){
    var isError = false

    fun doOnError() {
        // do non view related stuff
        // like a network call or something          
    }

    companion object {
        val instance by lazy { SingletonErrorHandler() }
    }
}

in the activity you can define

class ActivityA : AppCompatActivity() {
    fun onError() {
        SingletonErrorHandler.instance.isError = true
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.a_activity)
    }
}

in activity B

class ActivityB : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.b_activity)

        val errorHandler = SingletonErrorHandler.instance
        if(errorHandler.isError)
             errorHandler.doOnError()
    }
}
like image 167
HawkPriest Avatar answered Sep 30 '22 18:09

HawkPriest