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.
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'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..!
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.
I am great fan of Kotlin and how it allows us to write better code. One of the best features is interface implementation delegation which looks like this:
class A(val someObject:SomeInterface) : SomeInterface by someObject
someObject has to be singleton (object), has to be created using constructor after keyword by (but then you cannot reference to it, or maybe someone has idea how to do it?) or has to be provided in constructor.
In Android messy and bad world we are discouraged to use constructors in fragments and activites due to configuration changes. But how about this:
class MyFragment(val someObject:SomeInterface = SomeObjectImpl()):Fragment,SomeInterface by someObject
I tried to change configuration and event I allowed system to kill my appliction and still, everything is looking ok, my object is creating again and again with my fragment. Is this valid, or am I missing something?
Happy Kotlin everyone!
This is valid. The reason you're discouraged from overloading fragment constructors is that Android can recreate them, and it will use the default one: MyFragment()
But the way Kotlin implements default parameter values behind the scenes is by creating additional constructors. You can decompile your class and see it contains two constructors now, one receiving someObject, and another empty.
From the JVM perspective the empty constructor would look like this:
public A() {
this(new SomeObjectImpl());
}
Calling it will populate your fragment with new instances of implemented classes.
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