This Function is in a separate .kt file in my android studio compose project.
Has this to do something with the OptIn marker? Since all other functions which don't have this OptIn marker are working.
#OptIn(ExperimentalWearMaterialApi::class)
#Composable
fun SwipeDetector(): Swiped? {
Thank you.
From your description it sounds like you are dealing with a required opt in.
This means if a function calls another function that has the required OptIn annotation, this function needs to opt in as well. This can be solved by annotating the calling function OptIn as well, or marking the class in which the function as OptIn, or marking the whole file as OptIn.
#OptIn(ExperimentalWearMaterialApi::class)
fun callingSwipeDetector(…
//or the whole class
#OptIn(ExperimentalWearMaterialApi::class)
class ContainingFunctionCallingSwipeDetector…
//or on top of the file that contains the function
#file:OptIn(ExperimentalWearMaterialApi::class)
Related
I'm just trying to get started with Android development and Kotlin using Jetpack Compose. Note that, I'm a Kotlin novice, so I'm trying to learn along the way. I come from JavaScript/TypeScript background, so I'm trying to learn by thinking in JavaScript terms and implement in Kotlin terms by searching online.
I'm trying to list all installed applications on the device. While the app was working as expected up till now, I needed to add a feature to sort the installed app names. I referred to: https://www.bezkoder.com/kotlin-sort-list-objects/#Create_Class_for_handling_sorting. As soon as I added a custom class to sort the List<ApplicationInfo>, my app stopped building.
I have included my repo here: https://github.com/Hrishikesh-K/TryKotlin
If I comment these lines and this line as well, the app builds fine. With the current setup, I get an error:
Functions which invoke #Composable functions must be marked with the #Composable annotation
which points to line 21, character 18, which is the start of the word compare.
I don't understand why Compose would care about a custom class, it's not a Composable function after all. What am I missing?
In the compare method you are using LocalContext.current
override fun compare(o1 : ApplicationInfo, o2 : ApplicationInfo): Int {
return o1.loadLabel(LocalContext.current.packageManager).toString().compareTo(o2.loadLabel(LocalContext.current.packageManager).toString())
}
You can't use a #Composable functions if the method is not marked with the #Composable.
Use something different like:
data class CompareApplicationNames(val context: Context) : Comparator<ApplicationInfo> {
override fun compare(o1 : ApplicationInfo, o2 : ApplicationInfo): Int {
return o1.loadLabel(context.packageManager).toString().compareTo(o2.loadLabel(context.packageManager).toString())
}
}
Then just use:
Log.d("sorted:", listOfApplications.sortedWith(CompareApplicationNames(LocalContext.current)).toString())
I am trying to use a code snippet from the official android documentation (https://developer.android.com/training/printing/photos#kotlin) which is the doPhotoPrint() function in the code that I have attached, in order to learn how to use the PrintHelper class in Kotlin and Android Studio. See the attached image of the the code snippet:
The problem is that when I put the code in Main Activity in my test app, it keeps showing "activity?." as red. Why is this the case and how can I get the code to work so that is provides the user with the option to print? Thanks
The code you linked is just a general how to use a library function snippet - it's not put in any context, but we can assume it's probably written with a Fragment in mind. Fragments have a getActivity() method that returns the Activity it's currently attached to (or null if it's not)
Kotlin allows you to access getter and setter functions from Java code as if they were properties - so basically, instead of having to do value = getThing()
and setThing(newValue) you can treat it like a variable: value = thing, thing = newValue etc. So when you access the activity property in this code, it's really calling getActivity(). And because the result can be null, you use the ? to null-check it before trying to do anything with it.
Really what that snippet is saying is, this code needs access to a Context, and it's using an Activity as one in the example. If you have a Fragment, you can just drop this code right in. If you're in an Activity though, then you obviously don't need to get one - this is your Activity! And you don't need to null-check it either of course. (And there's no activity property or getActivity() method to access, which is why it's showing up red and unrecognised)
So you can just replace that stuff and the checking code around it with:
private fun doPhotoPrint() {
// using 'this' to pass the current activity as the context
val printHelper = PrintHelper(this).apply {
scaleMode = PrintHelper.SCALE_MODE_FIT
}
val bitmap = BitmapFactory.decodeResource(resources, R.drawable.droids)
printHelper.printBitmap("droids.jpg - test print", bitmap)
}
It is showing red because you have not declared the nullable object activity anyway before you use it
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)
}
ScreenDef is a class, I add a function setDevice for the class, which one is correct between Code A and Code B? why?
I think that Code B is correct, right?
Code C
data class ScreenDef(
val brightness: Int
): DeviceDef
class ScreenHelper(val mContext: Context) {
fun setScreen(aScreenDef: ScreenDef){
}
}
Code A
fun ScreenDef.setDevice(mContext: Context) {
ScreenHelper(mContext).setScreen(this)
}
Code B
fun ScreenDef.setDevice(mContext: Context) {
ScreenHelper(mContext).setScreen(it)
}
You should use this. it is referred as shorthand if there is only one parameter in lambdas.
context?.let {
it.resources.getInt(R.int.anyint) // just for example
}
In above snippet, it is the shorthand for lamda parameter(in case of only one parameter).
context?.let { cxt -> // here we have manually defined a parameter
cxt.resources.getInt(R.int.anyint) // just for an example
}
In this snippet, instead of it we have created cxt that is exactly same as it.
Actually you are taking the concept of Extension function wrong.
You are creating a data class ScreenDef and want to create an extension function to it, why? If you really want to have a member function just create a normal class and have a function in it.
Extension function should be created when target class is not maintained by you. For example: Activity, Fragments are not maintained by you and if you want to add a custom function, you have to extend them and do it. So to prevent it extension function comes into picture and they are really handy that's why we love it.
You can rather argue, whats wrong with creating extension function for a class created by us. It may or might not be true. It actually depends.
Let's take an example, suppose we have developed a library to draw simple symbols on canvas and there are several function we have created. It turned out to be so good that people are using it, we decided to created advanced version, that can draw more complex symbols that requires using our already developed simple lib. So when we extend the classes of simple lib we might need some functionality to improve some thing etc. in that case if we have imported our simple lib as dependency then its good to create extension function otherwise we would have to create one more child of that class and create desired function. If we have import our lib as source code, we can just go to the source fine and create a function inside it.
I hope it helps.
In the last year I've become a mobile developer and a functional programming admirer.
In each of the mobile arenas there are components with lifecycle methods that make up the meat of the app. The following will use Android and Kotlin as examples, but the same applies to iOS and Swift.
In Android, there are Activity's with lifecycle methods like onCreate(). You might also define a function, onButtonClicked(), which will do exactly what the name describes.
For the purposes of the question, let's say there's a variable defined in onCreate() that is used in a button click handler onButtonClickedPrintMessageLength() (This is usually the case - onCreate() is essentially Activity's setup method).
The example class would look like this:
class ExampleActivity: Activity() {
var savedStateMessage: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
savedStateMessage = "Hello World!"
}
fun onButtonClickedPrintMessageLength() {
System.out.println(savedStateMessage?.length)
}
}
Notice the declaration of savedStateMessage as a String? (nullable string) and the use of ?. (null safe call). These are required because the compiler cant guarantee that onCreate() will be called before onButtonClickedPrintMessageLength(). As developers though, we know that onCreate will always be called first* **.
My question is how can I tell the compiler about the guaranteed order of these methods and eliminate the null checking behavior?
* I suppose it's possible to new up our ExampleActivity and call onButtonClickedPrintMessageLength() directly, thus sidestepping the Android framework and lifecycle methods, but the compiler/JVM would likely run into an error before anything interesting happened.
** The guarantee that onCreate is called first is provided by the Android framework, which is an external source of truth and might break/function differently in the future. Seeing that all Android apps are based on this source of truth though, I believe it's safe to trust.
Although this won't answer your actual question, in Kotlin you can use lateinit to tell the compiler that you'll initialize a var at a later point in time:
lateinit var savedStateMessage: String
You'll get a very specific UninitializedPropertyAccessException if you try to use this variable before initializing it. This feature is useful in use cases like JUnit, where you'd usually initialize variables in #Before-annotated method, and Android Activitys, where you don't have access to the constructor and initialize stuff in onCreate().
As mentioned in another answer, lateinit is available as an option to defer initialization to a later point in a guaranteed lifecycle. An alternative is to use a delegate:
var savedStateMessage: String by Delegates.notNull()
Which is equivalent, in that it will report an error if you access the variable before initializing it.
In Swift this is where you would use an implicitly-unwrapped Optional:
class Example: CustomStringConvertible {
var savedStateMessage: String! // implicitly-unwrapped Optional<String>
var description: String { return savedStateMessage }
init() {
savedStateMessage = "Hello World!"
}
}
print(Example()) // => "Hello World!\n"
By using the operator ! at the end of String in the second line of the example you are promising that the variable will be set before it can be used. This is accomplished in the init method of the example. It's still an Optional but code can treat it as a String since it will be automatically unwrapped before each use. You must take care that the variable is never set to nil when it might be accessed or a runtime exception may be generated.