compose跨平台第二弹:体验composeforweb(代码片段)

datian1234 datian1234     2023-01-14     396

关键词:

前言

Compose跨平台第一弹:体验Compose for Desktop 中,我们已经了解了Compose-jb以及如何使用Compose-jb开发简单的桌面端应用,第二弹,我们就来了解下如何使用Compose-jb开发Web应用。相信看完这一弹之后你会对Compose-jb有新的了解。

环境要求

与Compose For Desktop的环境要求一致。

开发流程

创建项目

同样的,我们打开IDEA创建Compose Multiplatform项目,选择Single plaform,不过这里我们选择Platform为Web平台,如下图所示。

创建好项目后,来看项目目录结构,如下图所示。

可以看到同样的在配置文件中指定了平台配置,这一点是比较重要的,便于以后我们在原有项目基础上添加配置。并且以后我们会发现,这个配置也不一定在根目录中的build文件中,所以我们需要知道配置的含义,这一点目前规划在后续的弹中会单独分享。

项目结构

在jsMain文件夹下Main文件通过renderComposable的rootElementId属性与index.html中的div标签绑定,从而将页面在web中显示。index.html代码截图如下所示。

Main.kt代码截图如下所示。

当我看到这段代码之后,我心里是慌的,Div?style?attrs?这都是什么玩意啊,学了Compose的我都不知道,这也能叫跨平台?

这是Compose for Web专门提供的一套DOM API,Div组件也是为Web实现的对应Composeable组件,通过attrs方法设置标签属性。所以这些代码,都是无法直接在Android或Desktop平台上复用的。所以,从这一点来讲使用Compose实现跨平台,目前存在严重的割裂问题,和Flutter相比还是有一定的差距。

运行程序(./gradlew jsBrowserRun),页面如下图所示。

这是项目默认实现的一个加减计数器的功能。接下来我们来添加自己的组件。

添加输入框

和开发Desktop一样,我们先来添加一个输入框,在Compose for Web中输入框采用Input组件

,代码如下所示:

renderComposable(rootElementId = "root") 

    Div 
        P 
            Input(type = InputType.Text) 
        
        P 
            Input(type = InputType.Password)
        

        P 
            Button(attrs = 
                onClick 

                
            ) 
                Text("Login")
            
        
    

通过type属性指定输入框的类别分别为文字和密码,运行程序,结果如下图所示。

接着我们通过添加Text标签为输入框添加属性说明,修改部分的代码如下所示:

P 
    Text("用户名")
    Input(type = InputType.Text) 

P 
    Text("密码")
    Input(type = InputType.Password)

再次运行程序,结果如下图所示。

嗯,挺丑的。上述代码我们在最外层使用Div包裹是为了便于为这块区域设置一些属性,比如我们设置背景色为蓝色,代码如下所示。

Div(style 
   backgroundColor(Color.blue)
)
   ...

运行程序,结果如下所示。

好吧,更丑了… , Compose for Web 允许开发者基于 DSL 定义 Style 样式,但是到目前为止我的感觉是写的很累,感觉如果不会Web就无法写好Compose for Web,这叫哪门子的跨平台?

添加超链接

超链接直接使用A标签即可,比如这里我们添加一个用户隐私协议,代码如下所示。

P 
    A("https://www.baidu.com/")  
        Text("用户协议")
    

运行程序,结果如下图所示。

如果想用Compose写好Web,我觉得最主要的是Style DSL,但是在这里我们没办法一一展示。需要我们在项目中去实战。接下来,我们来实现与Desktop一样的查询数据功能。

实现查询数据功能

本来打算仍然借用「wanandroid」中「每日一问」接口的,但是这个接口存在跨域问题,导致无法请求,所以我们这里将接口返回的json数据,定义为Api文件中的data变量,Ktor的使用方式是一样的,所以并不影响实际结果。

定义HttpUtil类并实现getData方法,代码如下所示。

class HttpUtil 

    /**
     * 获取数据
     */
    suspend fun getData(): DemoReqData 
        val rockets = Json.decodeFromString<DemoReqData>(string = Api.data)
        return rockets
    

在Desktop中我们可以直接在Main 文件中直接调用取数据的方法,但是这里不行,因为renderComposable下无法启动协程。所以这里我们定义一个DataSource类继承自CoroutineScope,同样定义一个loadData方法,代码如下所示。

class DataSource : CoroutineScope 
    private var job = Job()
    override val coroutineContext: CoroutineContext
        get() = job

    private val _stateFlow = MutableStateFlow(DemoReqData())
    var stateFlow = _stateFlow.asStateFlow()

    fun loadData() 
        launch 
            _stateFlow.value = HttpUtil().getData()
        
    

这样我们可以在loadData方法中启动协程并调用HttpUtil中的getData方法,然后赋值给stateFlow,这一点得益于Flow 是 kotlinx 包下的组件,与平台无关。

最后,我们在Main中定义一个按钮,点击“请求数据”,然后将数据显示出来,代码如下所示。

renderComposable(rootElementId = "root") 

    val dataSource = DataSource()

    val data = dataSource.stateFlow.collectAsState()

    Button(attrs = 
        onClick 
            dataSource.loadData()
        

    ) 
        Text("请求数据")
    

    Div 
        repeat(data.value.data?.datas?.size ?: 0) 
            Div 
                P 
                    Text("作者:" + data.value.data?.datas?.get(it)?.author)
                
                P 
                    Text("标题:" + data.value.data?.datas?.get(it)?.title)
                
                P(
                    style 
                        height(1.px)
                        backgroundColor(Color.red)
                    
                ) 
            
        
    

这里将作者信息与标题显示出来,为了效果明显添加了一个红色的横线,运行程序,点击“请求数据”,结果如下图所示。

这样我们就使用Compose实现了一个Web端简单的查询数据功能。

写在最后

Compose For Web 中提供了更贴近 HTML 风格的 Composable API,所以UI代码无法与Android或Desktop的UI代码直接复用。但是逻辑层的代码都是可以共用的,目前Google也在推进解决这样的“割裂”问题,从目前来看,Compose跨平台还有一定的路要走,我们将在后续的第N弹中持续探索…

作者:黄林晴
链接:https://juejin.cn/post/7187306464875118651

文末福利

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。


相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

全套视频资料:

一、面试合集

二、源码解析合集


三、开源框架合集


欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取↓↓↓

ai作画第二弹

上次一次尝试AI作画,还是在6月份,详情可见《AI作画初体验》。那个时候使用的是Google开发的DD(DiscoDiffusion)系统,使用的版本为V5.0。DD作画的确令人惊艳,但没想到,不到两个月的时间,SD(StableDiffusion)斜... 查看详情

pythion第二弹

################################第二节################################################python中数据类型的常见的方法第一个数据类型字符串str字符串里面有很多的功能,叫方法.只要是字符串,就可以用里面的方法,方法有很多,不用刻意的去记住,因为... 查看详情

深入理解threadpoolexecutor第二弹(代码片段)

从源头解析ThreadPoolExecutor第二弹—ThreadPoolExecutor的内部类ThreadPoolExecutor主要包括如下内部类:其中AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy、DiscardPolicy表示任务的拒绝策略,当线程池的线程数量达到最大值并且阻塞队列已... 查看详情

springboot第二弹,配置文件详解-史上最全

参考技术A SpringBoot官方提供了两种常用的配置文件格式,分别是properties、YML格式。相比于properties来说,YML更加年轻,层级也是更加分明。强烈推荐使用YML格式 SpringBoot项目启动会扫描以下位置的application.properties或者appl... 查看详情

web前端-----第二弹css

CSS语法CSS规则由两个主要的部分构成:选择器,以及一条或多条声明。‘‘‘selector{property:value;property:value;...property:value}‘‘‘例如:h1{color:red;font-size:14px;}    css的四种引入方式 1.行内式       ... 查看详情

表单练习第二弹

---恢复内容开始---<bodytext="#33FF00"bgcolor="#33FF33"background="150358666450342800_a580xH.jpg">body里面加属性,字体颜色、背景色、背景图片。在body里面输入的属性是针对在body里面所有内容的属性。<formaction="../10.9表单/www.baidu.html"method=" 查看详情

线段树+rmq问题第二弹

   线段树+RMQ问题第二弹  上篇文章讲到了基于SparseTable解决RMQ问题,不知道大家还有没有印象,今天我们会从线段树的方法对RMQ问题再一次讨论。正式介绍今天解决RMQ问题的方法之前,我先对RMQ问题的概念再... 查看详情

lca问题第二弹

LCA问题第二弹 上次用二分的方法给大家分享了对LCA问题的处理,各位应该还能回忆起来上次的方法是由子节点向根节点(自下而上)的处理,平时我们遇到的很多问题都是正向思维处理困难而逆向思维处理比较容易,LCA问题... 查看详情

dom事件第二弹(uievent事件)

此文章主要总结UIEvent相关的事件,如有不对的地方,欢迎指正。一、uitls.js(绑定事件公共类)varfixs={‘focusin‘:{standard:‘focus‘,ie:‘focusin‘},‘focusout‘:{standard:‘blur‘,ie:‘foucsout‘},‘input‘:{standard:‘input‘,ie:‘propertychange‘}}v... 查看详情

有趣的网站-第二弹

1.预测您的死亡时间,通过输入出生日期,选择性别、BMI范围(可以通过页面下方输入身高、体重计算出)、生活态度和是否抽烟,点击查看按钮就可以得出结果。我测了我还能活52多年。。不过看着时间越来越少,心理感觉毛... 查看详情

获取免费的gpt网站指南(第二弹)

免费虽好,勿要贪杯前言GPT4free的原理是从大网站的接口中当普罗米修斯,如果换一个思路,公网上很多人都部署了自己的GPT服务,如果能够把他们利用起来,实际上我们平时问问题也够用了 查看详情

cookbook学习第二弹

1.5怎样实现一个按优先级排序的队列?并且在这个队列上面每次pop操作总是返回优先级最高的那个元素带有双下划线的方法,会在需要被调用的位置自动被调用带有单下划线的变量是私有变量 下面利用类heapq模块实现一个简... 查看详情

拿来吧你,compose尝鲜初体验!(代码片段)

前言Compose正式版在七月份的尾巴如期而至,我也写了一份Compose版本的项目,Demo其实比较简单。地址:github.com/mCyp/Hoo。这已经是它的第三个版本:第一版:Kotlin+Jetpack第二版:Flutter第三版:Compose+... 查看详情

liaoliao的四连做第二弹

liaoliao四连做第一弹1.bzoj3211:花神游历各国由于$10^9$以内的数最多只会被开方$10$次,所以我们可以用线段树维护然后剪枝..#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#defineLLlon 查看详情

hbase存取速度为啥快---第二弹

版权声明:本文为CSDN博主「九品下」的原创文章原文链接:https://blog.csdn.net/w892824196/article/HBase能提供实时计算服务主要原因是由其架构和底层的数据结构决定的,即由LSM-Tree(Log-StructuredMerge-Tree)+HTable(region分区)+Cache决定——客户... 查看详情

『pytorch』第二弹_张量

参考:http://www.jianshu.com/p/5ae644748f21#几个数学概念:标量(Scalar)是只有大小,没有方向的量,如1,2,3等向量(Vector)是有大小和方向的量,其实就是一串数字,如(1,2)矩阵(Matrix)是好几个向量拍成一排合并而成的一堆数字... 查看详情

线段树第二弹(区间更新)

          上篇文章,我们介绍了线段树的基本概念和单点更新、区间查询,今天,我们来接着上次的线段树问题继续深入研究。在解决线段树问题的过程中,我们会遇到要求修改区间中某一元... 查看详情

scratch编程第二弹

目标效果: 所需要展示的效果就是,天上的女巫飞来飞去,南关不断的眨眼,而猫头鹰也在不断的眨眼,------考察方向:单纯的循环结构的考察------方向,图形化编程循环考察---猫头鹰有两个背景,这种图形编程的效果就是... 查看详情