在gradle加了相关序列化和协程的依赖
之后common中加入entity

package com.example.mympp0application.entity

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class RocketLaunch (
@SerialName("flight_number")
val flightNumber:Int,
@SerialName("name")
val missionName:String,
@SerialName("date_utc")
val launchDateUTC:String,
@SerialName("success")
val launchSuccess:Boolean?,
)

再引入ktor(一个支持kotlin的http框架)
更改欢迎页
可以看到标注的一行进行了httpClient调用

package com.example.mympp0application

import com.example.mympp0application.entity.RocketLaunch
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.Json

class Greeting {

private val httpClient= HttpClient{
install(ContentNegotiation){
json(Json{
prettyPrint=true
isLenient=true
ignoreUnknownKeys=true
})
}
}

@Throws(Exception::class)
suspend fun greeting(): String {
val rockets:List<RocketLaunch> = httpClient.get("https://api.spacexdata.com/v4/launches").body()
val lastSuccessLaunch = rockets.last {it.launchSuccess==true}
return "Hello, ${Platform().platform.reversed()}!"+
"\nThere are only ${daysUntilNewYear()} left until New Year!"+
"\nThe last successful launch was ${lastSuccessLaunch.launchDateUTC} ð"
}

}

下面在安卓端和IOS端都进行了greeting的调用:

Android:

package com.example.mympp0application.android

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.mympp0application.Greeting
import android.widget.TextView
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {
private val scope = MainScope()

override fun onDestroy() {
super.onDestroy()
scope.cancel()
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val tv: TextView = findViewById(R.id.text_view)
tv.text = "Loading..."

scope.launch {
kotlin.runCatching{
/**
* The greeting() function is now called
* inside the coroutine launched in the main
* CoroutineScope
*/
Greeting().greeting()
}.onSuccess {
tv.text=it
}.onFailure {
tv.text=it.localizedMessage
}
}
}
}

IOS:

import SwiftUI
import shared

struct ContentView: View {
@ObservedObject private(set) var viewModel:ViewModel

var body: some View {
Text(viewModel.text)
}
}

extension ContentView{
class ViewModel: ObservableObject{
@Published var text = "Loading..."
init(){
Greeting().greeting{
greeting,error in
/**
When calling Kotlin suspend functions from Swift,
completion handlers might be called on threads other thant the main one
Tha's why DispatchQueue.main.async is used to update the text property
*/
DispatchQueue.main.async{
//Data will be loaded here
if let greeting = greeting {
self.text = greeting
}else{
self.text = error?.localizedDescription ?? "error"
}
}
}

}
}
}