kotlin call function with android view - android

We are trying to understand calling a function in Kotlin
The function looks like this
fun onSIMPLE(view: View){
val snack = Snackbar.make(view,"This is a simple Snackbar", Snackbar.LENGTH_LONG)
snack.show()
}
And the call is made this way
btnSB2.setOnClickListener {onSIMPLE(it)}
What we do not understand is how does one know to use the keyword "it"?
Who ever created the keyword "it" must have never searched the Web
We plugged every reasonable keyword in the ( ) to solve the issue
YES we also looked at the documentation
Is there a better way to construct the function or make the call?

it is the implicit name for a single parameter lambda. You can override as you wish, e.g:
btnSB2.setOnClickListener { view -> onSIMPLE(view)}

setOnClickListener expects a lambda as a parameter, using a Java-like approach, this should look like this:
btnSB2.setOnClickListener({
v:View -> onSIMPLE(it)
})
Also, if the lambda is the last parameter for a given function, it can be specified outside of the parenthesis, which would look like this:
btnSB2.setOnClickListener {
v:View -> onSIMPLE(it)
}
It is common for lambda functions to have a single parameter. For these functions, Kotlin maintains the it keyword. Knowing this, the code becomes:
btnSB2.setOnClickListener {
onSIMPLE(it)
}

Related

Kotlin inline function for checking if user is autheticated or not?

I want to execute a block of code after checking if user is authenticated or not. Something like this:
inline fun <T : Any, R> T?.isUserAuthenticated(callback: (T) -> R) {
FirebaseAuth.getInstance().currentUser?.let {
//Function call
} ?: kotlin.run {
FirebaseAuth.getInstance().signInAnonymously().addOnSuccessListener {
//Function call
}
}
This approach isn't working, but is there any alternative to this?
Inline functions in Kotlin should be used over regular functions when:
You desperately need to allocate memory more efficiently.
When a function accepts another function or lambda as an argument.
You need to prevent object creation and have better control flow.
Otherwise, inlining may cause the generated code to grow. Most likely there are also other situations when it is worth using inline functions but I only added a few (important) of them.
When it comes to checking if a user is authenticated or not, I would rather create a regular function that looks like this:
fun getAuthState() = auth.currentUser != null
And use it:
val isAuthenticated = getAuthState()
if(!isAuthenticated) {
auth.signInAnonymously().addOnCompleteListener(/*...*/)
}
Or if using Kotlin Coroutine:
if(!isAuthenticated) {
auth.signInAnonymously().await()
}
So it's one approach or the other.
I would add this function in a repository class so it can be used all across the entire project.
If you're interested in seeing some code, I recommend you check the following resource:
How to handle Firebase Authentication in clean architecture using Jetpack Compose?
And here is the corresponding repo.

In jetpack what is setContent? [duplicate]

Passing a lambda to the last parameter
In Kotlin, there is a convention that if the last parameter of a
function accepts a function, a lambda expression that is passed as the
corresponding argument can be placed outside the parentheses:
val product = items.fold(1) { acc, e -> acc * e }
What is the purpose of this syntax?
This syntax gives Kotlin great DSL capabilities, it makes functions look like language constructions. For example:
with(car) {
startUp()
goToDestination()
}
Here with looks like it is language construction, whereas it is a simple function, receiving lambda as the last parameter.
And this leads to such elegant things like Kotlin HTML DSL

what does it. mean in the context of alos operator

I am learning how to use the coroutines in kotlin. looking at some examples in the internet i found that within the context f the also operator the reference
it
is used. i could not find any explanation about the meaning of
it
please provide some brief explanantion about what does "it" mean
when you use the also method, it has 1 parameter.
Think of it in Java kinda like this:
foo.also(int it) {
// do stuff
}
In Kotlin, the it parameter is implicit (sometimes you might want to use it sometimes you don't).
If you want to rename it to something more readable you can
foo.also { newName ->
// do stuff with newName
}
Or just use it like it is
foo.also {
// do stuff with $it
}
So therefore when you are using a method (or a closure/lambda) if it has 1 parameter, then the implicit name of that parameter is always it.
Basically it represents the lambda parameter
let's say you want to perform anything on the variable but do to check the nullity first, you can do it like
var str:String?=null // str is of string type
now you can use it fail safe
str?.let{it:String// youll see like this
// now you can access str as **it**
}
it is the implicit name of a single parameter
For more information about it and this in scoping functions like also

Kotlin lambda compiles against java API but not against my own function

Here is a simplified example. This syntax works :
Handler().post({Log.v(TAG, "test")})
However, if I define this function
private fun doWithRunnable(toRun:Runnable) {
// whatever
}
And call it like this
doWithRunnable({Log.v(TAG, "test")})
Then I get the following error:
Required: RunnableFound: () -> Int
Both signatures look quite the same to me... what's the big difference?
In your Java example, you're taking advantage of the Java-interop feature for SAM Conversions. Unfortunately, this does not currently work for Kotlin interfaces, as the designers have deemed it unnecessary (there is some discussion on this see here).
Instead, you'd want to do something like:
fun doWithRunnable(runnable: () -> Any) {
// call it as `runnable()`
}
You could also define a typealias for this if you wanted (which is as close Kotlin comes to SAM syntax):
typealias RunMe = () -> Any
fun doWithRunnable(runnable: RunMe) {
runnable()
}
Note that currently, typealiases have to be declared at the top level, they can't be declared inside a class or method.

Kotlin execute optional action

I have a model with an optional higher-order function (() -> Unit)?
When I want to call that function, I'm wondering, how can I call it even been an optional.
I know this works
model.action?.invoke()
There is something similar to Swift?, where I could do:
model.action?()
I know, I can do too:
model.action?.let { action() }
Maybe this last one is the "better" way to go.
Do you know some "better" way?
Thanks
It's a matter of one's personal preference, but I'd stay with the first variant, i.e.
model.action?.invoke()
Simply because it's just the safe call of invoke operator and it does not have the burden of adding higher-level function (i.e. let) into the expression.
Btw, in some cases if you write something like model.action?.let { it() } in Idea (at least it works for Android Studio which is based on Idea), you'll get a warning saying that let is useless here and you can safely replace it with the plain safe call.
You may use the standard library function let as follows:
val actionResult = model.action?.let { it() }
Note that the receiver of let (model.action) is exposed as it inside the lamda.
Alternatively, and preferably IMO, invoke the function like this:
model.action?.invoke()
If the function returns unit, I’d use also, not let. The former is a side-effecting construct, the latter for returning a value.

Categories

Resources