英文:
ComponentActivity with Kotlin
问题
我的生成的Kotlin MainActivity 让我很困惑:
-
setContent 在文件 ComponentActivity.kt 中声明为
public fun ComponentActivity.setContent(parent: CompositionContext? = null, content: @Composable () -> Unit)
,但似乎与 ComponentActivity 类没有关系。在Kotlin中,如果只在新方法前面写类名和点号,你能在额外的文件中扩展一个类吗? -
MyAppTheme 是文件 Theme.kt 中的一个函数,但与任何类都没有关系,也没有返回类型。在它后面跟着花括号块是什么意思?
-
然后我们有一个 Surface 的方法调用,也后面跟着花括号块。
-
Greeting 创建了一个 Text 实例,但没有返回,所以它必须被丢弃并进行垃圾回收。
我一定在W3schools Kotlin教程中错过了所有这些东西。我在搜索中没有找到与Kotlin教程有关的 ComponentActivity。也许有人能为我解释这些神秘的构造?这与Java非常不同,我不知道这是否更好。
英文:
My generated MainActivity in Kotlin confuses me a lot:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
// A surface container using the 'background' color from the theme
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
Greeting("Android")
}
}
}
}
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
fun GreetingPreview() {
MyAppTheme {
Greeting("Android")
}
}
}
-
setContent is declared public fun ComponentActivity.setContent(parent: CompositionContext? = null, content: @Composable () -> Unit) in a file ComponentActivity.kt but there seems to be no relationship to the class ComponentActivity. Can you extend a class in Kotlin in an extra file if you just write the classname + dot in front of new methods?
-
MyAppTheme is a function in a file Theme.kt but with no relationship to a class and no return type. What does it mean to write it followed by by a block with curly brackets?
-
Then we have a method call of Surface also followed by a curly brackets block
-
Greeting creates a Text instance that is not returned so it must be lost and garbage collected.
I must have missed all that stuff in the W3schools kotlin tutorial. I haven't found a ComponentActivity with kotlin tutorial googeling. Maybe someone can enlight me about those cryptic constructs? This is quite different from java and I dont know if for the better.
答案1
得分: 0
大部分你提出的问题与Jetpack Compose有关,它是建立在Kotlin之上的领域特定语言(DSL),而不是典型的Kotlin代码。
第一个要点:这适用于任何Kotlin代码。您可以使用该语法编写扩展函数。您不是扩展类,而是编写一个可以像类的成员一样调用的函数,但从行为上来说,它实际上只是一个使用类类型作为参数的外部静态函数。
这个Kotlin特性的目的是使实用函数非常容易编写和使用,代码看起来更自然。例如:
Arrays.sort(myIntArray); // Java实用方法调用
vs.
myIntArray.sort() // Kotlin扩展函数调用
第二个要点:最后一个参数是函数引用的函数可以在括号外部调用lambda。如果函数引用是唯一参数,您根本不需要括号。这被称为“尾随lambda语法”。这个特性允许编写DSL样式的代码,在Jetpack Compose中广泛使用。这个特性还使lambda的使用看起来更清晰:
myButton.setOnClickListener( (button) -> {
Log.i(TAG, "Button clicked");
doSomething();
});
vs.
myButton.setOnClickListener {
Log.i(TAG, "Button clicked")
doSomething()
}
它还启用了作用域函数:
myLayout.myButton.setTextColor(Color.RED);
myLayout.myButton.setUseElipsis(true);
myLayout.myButton.setText("Hello world");
myLayout.myButton.startBlinkAnimation();
vs.
myLayout.myButton.apply {
textColor = Color.RED
isUseElipsis = true
text = "Hello world"
startBlinkAnimation()
}
第三个要点:这又是尾随lambda语法,但是lambda之前还有其他参数,因此仍然需要括号。
第四个要点:Compose进行了许多编译器“魔法”,所以不要太担心从其方法返回实例和垃圾回收的方式,这与您所熟悉的方式不太一样。Compose收集了从@Composable
函数构建的所有内容,并可能在幕后持有对它们的引用。编译器插件使用DSL来构建实际的UI。
英文:
Most of what you're asking has to do with Jetpack Compose, which is a DSL (domain specific language) built on top of Kotlin. It's not typical Kotlin code.
First bullet point: This does apply to any Kotlin code. You can write extension functions with that syntax. You are not extending the class. You are writing a function that can be called as if it were a member of that class, but behavior-wise it's really just an external, static function that uses the class type as an argument.
The point of this Kotlin feature is it makes utility functions very easy to write and use--code looks much more natural. For example:
Arrays.sort(myIntArray); // java utility method call
vs.
myIntArray.sort() // kotlin extension function call
Second bullet point: A function whose last argument is a function reference can be called with the lambda outside the parentheses. If the function reference is the only argument, you don't need the parentheses at all. It's called "trailing lambda syntax". This feature allows DSL style code to be written, and it is used extensively in Jetpack Compose. This feature also enables cleaner looking use of lambdas:
myButton.setOnClickListener( (button) -> {
Log.i(TAG, "Button clicked");
doSomething();
});
vs.
myButton.setOnClickListener {
Log.i(TAG, "Button clicked")
doSomething()
}
And it enables scope functions:
myLayout.myButton.setTextColor(Color.RED);
myLayout.myButton.setUseElipsis(true);
myLayout.myButton.setText("Hello world");
myLayout.myButton.startBlinkAnimation();
vs.
myLayout.myButton.apply {
textColor = Color.RED
isUseElipsis = true
text = "Hello world"
startBlinkAnimation()
}
Third bullet point: This is trailing lambda syntax again, but with other arguments that come before the lambda, so it still has parentheses.
Fourth bullet point: Compose does a lot of compiler "magic", so don't think too hard about instances being returned from its methods and garbage collection the way you're used to. Compose collects all the stuff that's being built from @Composable
functions and may be holding references to it all under the hood. The compiler plugin uses the DSL to build your actual UI.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论