Kotlin Multiplatform项目探索之KMChat

news2024/11/13 15:02:33

Kotlin Multiplatform项目探索之KMChat

kotlin-multiplatform-use-cases
这是当前在 Kotlin Multiplatform 官方文档中提议的用例结构。Kotlin Multiplatform 中包含的许多子组件已经发布了稳定版本,即使目前不稳定的组件也在迅速更新。

本文中的演示项目包括 Compose Multiplatform - Web (Experimental)、iOS (Alpha) 和 Kotlin Multiplatform - Kotlin/Native (Beta)。在进行产品项目开发时,使用这种方法可能会导致一些问题。

通用代码随处可见

在开发软件时,各个平台上都存在重复的实现,被称为通用代码。这项任务不仅需要开发成本,还包含了许多开销,比如通信成本。JetBrains 提议使用 Kotlin Multiplatform,可以将通用代码开发为单个代码库,有效地解决了这些问题。

KMChat

这是我实现的一个聊天应用项目,旨在更好地理解官方文档中提出的用例。通过这个项目,我将学习如何使用Kotlin Multiplatform编写通用代码,并将其应用于所有平台。

我还使用Compose Multiplatform实现了所有平台的用户界面。

预览结果

  • 创建房间 → 加入房间 → 设置用户名
    Desktop / Web / AOS / iOS
    这是仅实现了聊天服务的最少功能的客户端的结果。您可以通过使用Compose多平台实现UI在所有平台上的结果。

Github

  • https://github.com/ColaGom/km-chat-common
  • https://github.com/ColaGom/km-chat-backend
  • https://github.com/ColaGom/km-chat-client

工程结构

kmchat structure
常用存储库由客户端和后端存储库中的子模块导入。

Common

  • 它包括聊天服务中使用的共同代码。
  • 我决定将演示项目的共同代码中包括DTO类和用例,这些类和用例同样包含在客户端和后端的业务逻辑中。

DTO

data class Chat
data class ChatMessage
data class ChatRoom
data class ChatUser

data class SendChat
data class CreateChatRoom
data class DeleteChatRoom

UseCase

interface UseCase<INPUT, OUTPUT> {
    suspend fun execute(input: INPUT): OUTPUT
}

interface CreateChatRoomUseCase : UseCase<CreateChatRoom, ChatRoom>
interface GetAllChatRoomUseCase : VoidUseCase<List<ChatRoom>>
interface GetChatRoomUseCase : UseCase<Long, ChatRoom?>

OverView common

overview dependency or data flow
后端和客户端项目均使用UseCaseImpl实现业务逻辑。

后端 — ktor

  • 实现了聊天室和与用户相关的API功能。
  • 使用WebSocket实现了聊天功能。
  • 存储库采用内存方式实现存储所有数据。

客户端 — Compose Multiplatform

  • 支持AOS、iOS、Web和桌面平台。
  • 使用Kotlin Multiplatform实现了所有平台的客户端逻辑。
  • 使用Compose Multiplatform实现了所有平台的用户界面。

我尝试了两种使用Compose Multiplatform的方式。

  1. 使用Compose multiplatform实现整个屏幕 (Web, Desktop)。
//in shared common
@Composable
fun ChatApp() {
    var selectedRoom by remember {
        mutableStateOf<ChatRoom?>(null)
    }

    Theme {
        Surface {
            Column(modifier = Modifier.fillMaxSize()) {
                val room = selectedRoom
                if (room != null) {
                    ChatScreen(room.id)
                    DisposableEffect(room) {
                        onDispose {
                            selectedRoom = null
                        }
                    }
                } else {
                    ChatRoomListScreen {
                        selectedRoom = it
                    }
                }
            }
        }
    }
}
  1. 在本地 UI(AOS、iOS)中实现复合 UI。
class MainActivity : ComponentActivity() {
    private val chatLauncher = registerForActivityResult(ChatActivity.Contract()) { }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ChatRoomListScreen(
                onClickRoom = { room ->
                    chatLauncher.launch(room.id)
                }
            )
        }
    }
}
@main
struct iOSApp: App {
    var body: some Scene {
        WindowGroup {
            MainView()
        }
    }
}

protocol ListViewListener : AnyObject {
    func clickRoom(room: Km_chat_commonChatRoom)
}

class MainViewModel: ObservableObject, ListViewListener {
    @Published var selectedRoom: Km_chat_commonChatRoom?
    
    var roomId: Int64 { ... }
    var entered: Bool { ... }
    
    func clickRoom(room: Km_chat_commonChatRoom) {
        selectedRoom = room
    }
}

struct MainView: View{
    @StateObject private var viewModel = MainViewModel()
    
    var body: some View {
        ListView(listener: viewModel)
            .sheet(isPresented: $viewModel.entered, content: { ChatView(roomId: viewModel.roomId) })
    }
}

struct ChatView: UIViewControllerRepresentable {
    var roomId: Int64
    
    func makeUIViewController(context: Context) -> UIViewController {
        return ControllersKt.ChatController(roomId: roomId)
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
    }
}

struct ListView: UIViewControllerRepresentable { ... }

结论

使用Kotlin Multiplatform似乎可以减少在各个层中存在的重复代码。

以下是将Kotlin Multiplatform应用于三层分层项目的两种方式的描述。

普通结构


上图显示了一个典型工作客户端和后端的结构。我假设所有项目都是按照三层结构进行开发的。在整个层中常常存在大量重复的代码。

使用Compose多平台技术


上图显示了KMChat的结构。我使用Kotlin多平台来共享通用代码,甚至为所有客户端实现用户界面。这种方法有潜力在某些平台(Web、iOS)上显著降低用户界面的质量,与本地(Native)相比。

共享演示业务,本地用户界面


上图仅显示演示业务层作为共享模块实现,UI作为本地UI实现。它在保持本地UI开发优势的同时,减少了多个层次的代码重复。

共享业务逻辑及平台组件构建UI


对于具有稳定性的平台,使用Compose实现UI,而其他平台使用本机UI。

参考

https://kotlinlang.org/lp/multiplatform/
https://kotlinlang.org/docs/multiplatform.html
https://www.jetbrains.com/lp/compose-multiplatform/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/690809.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【微服务架构设计和实现】4.9 微服务测试和部署最佳实践

往期回顾&#xff1a; 第一章&#xff1a;【云原生概念和技术】 第二章&#xff1a;【容器化应用程序设计和开发】 第三章&#xff1a;【基于容器的部署、管理和扩展】 第四章&#xff1a;【4.1 微服务架构概述和设计原则】 第四章&#xff1a;【4.2 服务边界的定义和划分…

STM32单片机(六)TIM定时器 -> 第二节:TIM定时中断练习2(定时器外部时钟)

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

如何看待社交媒体的时间管理和沉迷问题?

在当今数字化时代&#xff0c;社交媒体已经成为了人们生活中不可或缺的一部分。然而&#xff0c;社交媒体的普及也带来了一个问题&#xff1a;时间管理和沉迷。本文将从多个角度对社交媒体的时间管理和沉迷问题进行分析&#xff0c;并探讨如何合理利用社交媒体并避免沉迷。 第…

【计算机视觉】DINO

paper&#xff1a;Emerging Properties in Self-Supervised Vision Transformers 源码&#xff1a;https://github.com/facebookresearch/dino 20230627周二目前只把第一部分看完了。 论文导读&#xff1a;DINO -自监督视觉Transformers - deephub的文章 - 知乎、 DINO原理…

C生万物 | 细说动态内存管理【附经典笔试题】

文章目录 一、为什么存在动态内存分配二、动态内存函数的介绍1、malloc和free2、calloc3、reallocrealloc扩容机制&#xff1a;【本地扩容】和【异地扩容】实际应用&#xff1a;数据结构之【顺序表】与【顺序栈】 三、常见的动态内存错误1、对NULL指针的解引用操作2、对动态开辟…

Redisson源码-多线程之首个获取锁的线程加解锁流程

Redisson源码-多线程之首个获取锁的线程加解锁流程 简介 当有多个线程同时去获取同一把锁时&#xff0c;第一个获取到锁的线程会进行加解锁&#xff0c;其他线程需订阅消息并等待锁释放。 以下源码分析基于redisson-3.17.6版本&#xff0c;不同版本源码会有些许不同需注意。 …

数据结构--单链表的插入删除

数据结构–单链表的插入&删除 目标 单链表的插入&#xff08;位插、前插、后插&#xff09; 单链表的删除 单链表的插入 按为序插入(带头结点) ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e。 思路&#xff1a;找到第i-1个结点,将新结点插入其…

软件工程期末报告(登录注册部分)

云小智微校园工具系统的设计与实现成员1注册模块 第一章 绪论 系统的背景描述和概述&#xff1a;可以描述系统服务的对象是学生,满足他们查询课程安排和上课时间的需求。目前市场上确实存在这方面的需求,这款app可以方便学生管理课程。系统采用客户端-服务器架构,运行在安卓平…

自学黑客(网络安全),一般人我劝你还是算了吧(自学网络安全学习路线--第十章 公钥基础设施-PKI)【建议收藏】

文章目录 一、自学网络安全学习的误区和陷阱二、学习网络安全的一些前期准备三、自学网络安全学习路线一、PKI概述1、理论基础2、PKI提供的安全服务 二、数字证书1、数字证书的格式2、数字证书的生命周期3、用JAVA工具生成数字证书 三、PKI组成四、PKI功能五、信任模型六、相关…

基于 Redis 手写一个“秒杀”

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

Git分布式版本控制工具 —— 详细笔记

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

现代操作系统(中)

第三章 内存管理 概述 内存&#xff08;RAM&#xff09;是计算机中一种需要认真管理的重要资源。 经过多年探索&#xff0c;人们提出了分层存储器体系&#xff08;memory hierarchy&#xff09;的概念&#xff0c;即在这个体系中&#xff0c;计算机有若干兆&#xff08;MB&a…

统信UOS系统开发笔记(七):在统信UOS系统上使用linuxdeployqt发布qt程序

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/131411975 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…

qt QSqlRelationalTableModel 详解

背景知识&#xff1a; Qt SQL的API分为不同层&#xff1a; 驱动层 驱动层 对于QT是基于C来实现的框架&#xff0c;该层主要包括QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorbase、QSqlDriverPlugin and QSqlResult。这一层提供了特定数据库和SQL API层之间的底层桥梁…

Problem I Rank LED题解 - 2018年第一届GXCPC广西大学生程序设计大赛 正式赛

Problem I Rank LED题解 题目大意 ‘0’到‘9’的数字亮线依次为{6、2、5、5、4、5、6、3、7、6}。 Luras想修改每条光线的位置&#xff0c;使她的新等级尽可能小&#xff0c;同时新等级也是一个不带任何前导零的正整数。 另外&#xff0c;光线总数应与开始时相同。 官方题…

【AIGC】1、爆火的 AIGC 到底是什么 | 全面介绍

文章目录 一、AIGC 的简要介绍二、AIGC 的发展历程三、AIGC 的基石3.1 基本模型3.2 基于人类反馈的强化学习3.3 算力支持 四、生成式 AI&#xff08;Generative AI&#xff09;4.1 单模态4.1.1 生成式语言模型&#xff08;Generative Language Models&#xff0c;GLM&#xff0…

消息处理机制(AOSP4.4.2)

消息处理机制&#xff08;AOSP4.4.2&#xff09; Android 应用程序是通过消息来驱动的&#xff0c;系统为每一个应用程序维护一个消息队列&#xff0c;应用程序的主线程&#xff0c;不断地从这个消息队列中获取消息&#xff08;Looper&#xff09;&#xff0c;然后对消息进行处…

STM32单片机(三)第二节:GPIO输出练习2(LED流水灯)

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

3 分钟为英语学习神器 Anki 部署一个专属同步服务器

原文链接&#xff1a;https://icloudnative.io/posts/anki-sync-server/ Anki 介绍 Anki 是一个辅助记忆软件&#xff0c;其本质是一个卡片排序工具--即依据使用者对卡片上的自定义内容进行主动测试、自我评判后&#xff0c;其内部算法根据评判结果更改每张卡片下次测试时间的…

将win上的文件传输到Ubuntu虚拟机

首先获取Ubuntu系统的ip地址&#xff0c;在Ubuntu的Terminal中输入ifconfig&#xff0c;可以看到Ubuntu的ip地址 可以看到我电脑的ip地址是10.0.2.15。更改虚拟机的网络连接 这里以VirtualBox为例&#xff0c;打开VirtualBox设置&#xff0c;选择网络&#xff0c;将连接方式改…