krtko
03/15/2020, 7:16 PM//LoginViewController is a pure kotlin class that inherits from the MPP class ViewController. ViewController contains several platform specific fields such as `context` on Android
class LoginViewController: ViewController {
fun someButtonWasPressed() {
//A button was pressed callback
//uh oh we need to drop into native code for some reason
android { //An auto generated inlined lambda for the Android MMP
this.context //we have access to LoginViewController's Android side
this.androidDoSomething(this.context)
}
ios { //An auto generated inlined lambda for the iOS MMP
NSLog("You have access to anything from the iOS MP project")
val appDelegate = UIApplication.shared.delegate as AppDelegate
}
}
@platform("android") fun androidDoSomething(context: Context) { //can have platform specific arguments
//this method can only be called from an android context
Log.d("hi","from android")
}
//this could also be nested in some "subclass" like structure like `android { fun androidDoSomething(context: Context) {} }`
}
This produces messier and harder to read code in most circumstances, however I think it provides huge benefits in these particular cases:
1. Onboarding new users and beginners. Explaining the current MP project set up is not easy. I think if someone can start a project or contribute to a code base in the fashion above it will be significantly more clear to them. It's also a lot simpler to grasp out of the box vs the Actual/Expect system. Theres no indirection weaving back and forth between the different subproject for each platform.
2. Prototyping. The current Actual/Expect system works very well. It forces you to cleanly separate platform specific code from common code. Thats great except this can get in the way for when you are prototyping something and you just need to get the whole thing running in the most quick and simple fashion possible. I think the above system helps solve that as it reduces the need for nested platform code.
3. Simple platform calls. The current Actual/Expect system adds a lot of overhead for small platform specific methods. If the method is only ever going to be 1-3 lines per platform, its a lot of boiler plate to have a separate file for each platform specific instance of the method
----
2. Abstract classes with the ability to declare abstract specific platform code:
Ex.
Library author
abstract class ViewController {
@platform("android") abstract fun getView(context: Context): View //even tho we are in common kotlin, the method declaration can access Android
@platform("iOS") abstract fun getView(): UIView //even tho we are in common kotlin, the method declaration can access iOS
}
Library consumer
class LoginViewController: ViewController {
@platform("android") override fun getView(context: Context): View {
//inflate and return a view
}
@platform("iOS") override fun getView(): UIView {
val view = UIView()
return view
}
}
Library authors can currently do something like this by having an Actual/Expect abstract class with specific abstract methods for a given platform. My main issue with doing this is its not as clear to the library consumer and it requires more class nesting than the example above
----Luoqiaoyou
03/16/2020, 2:43 AMInline
will cause unreadable. Combining Jepack Compose with SwiftUI through the Kotlin compiler might be a better way to hide UI layer differentiation. For now, flutter may be better, but it requires an extra learning costLuoqiaoyou
03/16/2020, 2:46 AMkrtko
03/16/2020, 3:38 AMkrtko
03/16/2020, 3:39 AMLuoqiaoyou
03/16/2020, 3:45 AMLuoqiaoyou
03/16/2020, 3:58 AMkrtko
03/16/2020, 5:02 AMkrtko
03/16/2020, 5:06 AMLuoqiaoyou
03/16/2020, 6:35 AMkrtko
03/16/2020, 5:14 PMkrtko
03/16/2020, 5:20 PMkrtko
03/16/2020, 5:20 PMLuoqiaoyou
03/17/2020, 3:12 AMLuoqiaoyou
03/17/2020, 3:13 AMjson {
"data" to json {
"status_code" to 0
}
"required" to jsonArray { +"s" }
}
this case cause same error