I'm using Kotlin for development. When I reached the official Android tutorial's fragment section, I came across the supportFragmentManager. Which is available to use as a variable in Kotlin, whereas in java we can call its equivalent method getSupportFragmentManager().
I wonder where is the supportFragmentManager variable defined as I could not see anything like a variable declaration with that name, however clicking that variable took me to the following method inside fragmentActivity.java class.
/**
* Return the FragmentManager for interacting with fragments associated
* with this activity.
*/
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
How does this method come to be accessible as a variable in Kotlin whereas in java we've to access like a regular method? Any help would be appreciated.
Actually, in Kotlin when you call supportFragmentManager it's not variable, Any Java method contains get prefix (without argument) in the method in Kotlin it will be called like a variable without get word
Methods that follow the Java conventions for getters and setters (no-argument methods with names starting with get and single-argument methods with names starting with set) are represented as properties in Kotlin. Boolean accessor methods (where the name of the getter starts with is and the name of the setter starts with set) are represented as properties which have the same name as the getter method.
Read more about here
This is something like the getter and setter method in Kotlin. You don't need to describe getProperty() and setProperty() method to access/update value of property.
You can know more about how it actually works with an example from this question/answers.
I hope it will help you.
Happy coding..!
Related
material-components-android-codelabs is a git repo of demo code for material components. In the 102-starter branch of this repo, in LoginFragment.kt, there's this bit of code
(actvity as NavigationHost).navigateTo(ProductGridFragment(),false)
In the import statements, nothing in there seems to indicate where activity comes from and using android studio to find any declaration goes to a function with the signature public final FragmentActivity getActivity(). How is activity set and brought into the scope of the fragment?
Kotlin allows you to get and set properties directly without calling the method. E.g. instead of calling getActivity, you can just use activity. So (actvity as NavigationHost) actually translates to (getActivity() as NavigationHost)
Check the Kotlin reference here. Quote from the linked documentation:
To use a property, simply refer to it by its name
getActivity() is a method on Fragment instances, and Kotlin allows you to access Java-style setters and getters as though they're properties:
// getters
val newThing = stuff.getThing()
val newThing = stuff.thing
// setters
stuff.setThing(newThing)
stuff.thing = newThing
// boolean setters
dog.setGood(true)
dog.isGood = true
// boolean getters
val goodBoy = dog.isGood()
val goodBoy = dog.isGood
note that the property versions look the same whether you're getting or setting, you're just reading and writing to a single "property". Under the hood, it's making the call to the relevant function.
Fragment has a function: final public FragmentActivity getActivity()
-> since you're in the scope of a fragment, and the function is in the fragment scope, too, you don't need any import
To be able to use this activity reference, your fragment needs to be attached to an activity. => This should happen somewhere around onAttatch().
Last tip: when you're in a lifecycle where you're sure you have a backing activity, you can use requireActivity() to avoid unnecessary null-checks
I am learning to develop android apps in kotlin. I am using android studio 4.0.1. I dragged a switch onto a layout and set its state to true by default with
switch.setChecked(true)
But the IDE suggested I change it to
switch.isChecked()
, which wasn't what I wanted. Then I just happened to enter
switch.isChecked = true
and it worked.
My question is isChecked is a function and we don't invoke it that way. But somehow this worked. Why?
Thank you very much.
Here's a quote from Calling Java code from Kotlin: Getters and Setters:
Methods that follow the Java conventions for getters and setters
(no-argument methods with names starting with get and single-argument
methods with names starting with set) are represented as properties in
Kotlin. Boolean accessor methods (where the name of the getter starts
with is and the name of the setter starts with set) are represented as
properties which have the same name as the getter method.
Since Switch is a class created in Java and has setChecked and isChecked methods, Kotlin can synthesize an isChecked property for you so that accessing it from Kotlin can feel more idiomatic:
switch.isChecked = true
println(switch.isChecked) // prints "true"
as of Android 11 using mParent from Activity.java is on the list of greylisted (https://developer.android.com/about/versions/11/test-changes aka banned) things. The relevant line from the article is below:
Landroid/app/Activity;->mParent:Landroid/app/Activity; # Use androidx.fragment.app.Fragment and androidx.fragment.app.FragmentManager instead.
However, does this mean I cannot use the corresponding getter, Activity.getParent() ? I imagine the getter would be fine, just not changing the variable, because if the getter was banned then they would list that explicitly (as they list other getters) but the comment to use Fragment or FragmentManager is throwing me off.
getParent() is a public method on Activity. You do not need reflection to use it, and you can call it on every Android version.
Well I have a WebView, and the following property setting works:
webview.settings.cacheMode = WebSettings.LOAD_NO_CACHE
but not this one:
webview.settings.appCacheEnabled = false
Instead, I have to use the old way:
webview.settings.setAppCacheEnabled(false)
Can you tell me why? Thanks.
According to the official documentation:
Note that, if the Java class only has a setter, it will not be visible as a property in Kotlin, because Kotlin does not support set-only properties at this time.
If you look at the WebSettings abstract class, you'll see it only has public abstract void setAppCacheEnabled(boolean flag); method and no getters for this property, hence Kotlin doesn't allow using a property access syntax here.
Actually, it's worth noting that while creating synthetic property, not only Kotlin looks for setter and getter methods that follow Java conventions, but it also infers property's type from the getter which comes in play in case of subclasses overriding getter methods that return more specific type than their superclasses.
In this question there is one line,
findViewById(R.id.go_to_play_store).setOnClickListener(this::goToPlayStore);
how does this line is exactly handling the click listener ?
Java8 introduces concept of Method references and Functional interfaces. If function onClickListener requires a function with one argument(a.k.a Functional Interface) then if return types and argument types match your function(which is goToPlayStore) then you can pass its reference as functional interface.
This is the new JAVA 8 language feature Lambda Expressions.
:: refer to a new syntax in Java 8 known as method references. You can reference a class or instance and pass along the method that will handle the event
On click its calling function called goToPlayStore () located in that activity or fragment.
its Method references in Java 8
Which allows us to refer to an existing method by name. Method references can be used in place of lambda expressions as long as they satisfy the requirements of the functional interface.
For static methods the syntax is
Classname::methodName