Compose跨平台第三弹:体验Compose for iOS_implementation(compose ...

打印 上一主题 下一主题

主题 824|帖子 824|积分 2472

届时Compose-jb + KMM 将实现Kotlin全平台。

搭建项目

创建项目

由于目前Compose for iOS阶段还在试验阶段,所以我们无法利用Android Studio或者IDEA直接创建Compose支持iOS的项目,这里我们采用之前的方法,先利用Android Studio创建一个KMM项目,如果你不知道怎样创建一个KMM项目,可以参照之前的这篇文章KMM的初次尝试~ ,项目目次布局如下所示。

创建好KMM项目后我们必要添加Compose跨平台的相干设置。
添加设置

起首在settings.gradle文件中声明compose插件,代码如下所示:
  1. pluginManagement {
  2.     repositories {
  3.         google()
  4.         gradlePluginPortal()
  5.         mavenCentral()
  6.         maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
  7.     }
  8.     plugins {
  9.         val composeVersion = extra["compose.version"] as String
  10.         id("org.jetbrains.compose").version(composeVersion)
  11.     }
  12. }
复制代码
这里compose.version的版本号是声明在gradle.properties中的,代码如下所示:
  1. compose.version=1.3.0
复制代码
然后我们在shared模块中的build文件中引用插件
  1. plugins {
  2.     kotlin("multiplatform")
  3.     kotlin("native.cocoapods")
  4.     id("com.android.library")
  5.     id("org.jetbrains.compose")
  6. }
复制代码
并为commonMain添加compose依赖,代码如下所示:
  1. val commonMain by getting {
  2.     dependencies {
  3.         implementation(compose.ui)
  4.         implementation(compose.foundation)
  5.         implementation(compose.material)
  6.         implementation(compose.runtime)
  7.     }
  8. }
复制代码
sync之后,你会发现一个错误警告:uikit还处于试验阶段并且有很多bug…

uikit就是compose-jb袒露的UIKit对象。为了能够利用,我们必要在gradle.properties文件中添加如下设置:
  1. org.jetbrains.compose.experimental.uikit.enabled=true
复制代码
添加好设置之后,我们先来运行下iOS项目,确保添加的设置是无误的。
果然,不运行不知道,一运行吓一跳

这个问题困扰了我两三天,实在是无从动手,毕竟现在相干的资料很少,颠末N次的搜索,终极办理的方案很简单:Kotlin版本升级至1.8.0就可以了。
  1. kotlin("android").version("1.8.0").apply(false)
复制代码
再次运行项目,结果如下图所示。

不外这是KMM的iOS项目,接下来我们看怎样利用Compose编写iOS页面。
开始iOS之旅

我们更换掉iOSApp.swift中的原有代码,更换后的代码如下所示:
  1. import UIKit
  2. import shared
  3. @UIApplicationMain
  4. class AppDelegate: UIResponder, UIApplicationDelegate {
  5.     var window: UIWindow?
  6.     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  7.         window = UIWindow(frame: UIScreen.main.bounds)
  8.         let mainViewController = Main_iosKt.MainViewController()
  9.         window?.rootViewController = mainViewController
  10.         window?.makeKeyAndVisible()
  11.         return true
  12.     }
  13. }
复制代码
上面的代码看不懂没关系,我们只来看获取mainViewController的这一行
  1. let mainViewController = Main_iosKt.MainViewController()
复制代码
Main_iosKt.MainViewController是通过新建在shared模块iOSMain目次下的main.ios.kt文件获取的,代码如下所示:
  1. fun MainViewController(): UIViewController =
  2.     Application("Login") {
  3.         //调用一个Compose方法
  4.     }
复制代码
接下来所有的事情就都可以交给Compose了。
实现一个登录页面

由于页面这部门是公用的,所以我们在shared模块下的commonMain文件夹下新建Login.kt文件,编写一个简单的登录页面,代码如下所示:
  1. @Composable
  2. internal fun login() {
  3.     var userName by remember {
  4.         mutableStateOf("")
  5.     }
  6.     var password by remember {
  7.         mutableStateOf("")
  8.     }
  9.     Surface(modifier = Modifier.padding(30.dp)) {
  10.         Column {
  11.             TextField(userName, onValueChange = {
  12.                 userName = it
  13.             }, placeholder = { Text("请输入用户名") })
  14.             TextField(password, onValueChange = {
  15.                 password = it
  16.             }, placeholder = { Text("请输入密码") })
  17.             Button(onClick = {
  18.                 //登录
  19.             }) {
  20.                 Text("登录")
  21.             }
  22.         }
  23.     }
  24. }
复制代码
上述代码声明确一个用户名输入框、暗码输入框和一个登录按钮,就是简单的Compose代码。
然后必要在main.ios.kt中调用这个login方法:
  1. fun MainViewController(): UIViewController =
  2.     Application("Login") {
  3.         login()
  4.     }
复制代码
运行iOS程序,结果如下图所示:

嗯~,Compose 在iOS上UI险些可以做到100%复用,还有不学习Compose的理由吗?
实现一个双端网络请求功能

在之前的第1弹和第2弹中,我们分别实现了在Desktop、和Web端的网络请求功能,现在我们对之前的功能在iOS上再次实现。
添加网络请求设置

起首在shared模块下的build文件中添加网络请求相干的设置,这里网络请求我们利用Ktor,详细的可参照之前的文章:KMM的初次尝试~
设置代码如下所示:
  1. val commonMain by getting {
  2.     dependencies {
  3.         ...
  4.         implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
  5.         implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
  6.         implementation("io.ktor:ktor-client-core:$ktorVersion")
  7.         implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
  8.         implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
  9.     }
  10. }
  11. val iosMain by getting {
  12.     dependencies {
  13.         implementation("io.ktor:ktor-client-darwin:$ktorVersion")
  14.     }
  15. }
  16. val androidMain by getting {
  17.     dependencies {
  18.         implementation("io.ktor:ktor-client-android:$ktorVersion")
  19.     }
  20. }
复制代码
添加接口

这里我们仍旧利用「wandroid」中的每日一问接口 :wanandroid.com/wenda/list/…
DemoReqData与之前系列的实体类是一样的,这里就不重复展示了。
创建接口地址类,代码如下所示。
  1. object Api {
  2.     val dataApi = "https://wanandroid.com/wenda/list/1/json"
  3. }
复制代码
创建HttpUtil类,用于创建HttpClient对象和获取数据的方法,代码如下所示。
  1. class HttpUtil {
  2.     private val httpClient = HttpClient {
  3.         install(ContentNegotiation) {
  4.             json(Json {
  5.                 prettyPrint = true
  6.                 isLenient = true
  7.                 ignoreUnknownKeys = true
  8.             })
  9.         }
  10.     }
  11.     /**
  12.      * 获取数据
  13.      */
  14.     suspend fun getData(): DemoReqData {
  15.         val rockets: DemoReqData =
  16.             httpClient.get(Api.dataApi).body()
  17.         return rockets
  18.     }
  19. }
复制代码
这里的代码我们应该都是比力熟悉的,仅仅是换了一个网络请求框架而已。现在公共的业务逻辑已经处理好了,只必要页面端调用方法然后剖析数据并展示即可。
编写UI层

由于Android、iOS、Desktop三端的UI都是完全复用的,所以我们将之前实现的UI搬过来即可。代码如下所示:
  1. Column() {
  2.     val scope = rememberCoroutineScope()
  3.     var demoReqData by remember { mutableStateOf(DemoReqData()) }
  4.     Button(onClick = {
  5.         scope.launch {
  6.             try {
  7.                 demoReqData = HttpUtil().getData()
  8.             } catch (e: Exception) {
  9.             }
  10.         }
  11.     }) {
  12.         Text(text = "请求数据")
  13.     }
  14.     LazyColumn {
  15.         repeat(demoReqData.data?.datas?.size ?: 0) {
  16.             item {
  17.                 Message(demoReqData.data?.datas?.get(it))
  18.             }
  19.         }
  20.     }
  21. }
复制代码
获取数据后,通过
Message方法
将数据展示出来,这里只将作者与标题内容体现出来,代码如下所示。
  1. @Composable
  2. fun Message(data: DemoReqData.DataBean.DatasBean?) {
  3.     Card(
  4.         modifier = Modifier
  5.             .background(Color.White)
  6.             .padding(10.dp)
  7.             .fillMaxWidth(), elevation = 10.dp
  8.     ) {
  9.         Column(modifier = Modifier.padding(10.dp)) {
  10.             Text(
  11.                 text = "作者:${data?.author}"
  12.             )
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

飞不高

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表