实战:将 Android 多模块应用迁移到 Kotlin Multiplatform + Compose Multiplatform
最近把自己的 NBA 数据应用 HoopsNow 从纯 Android 多模块架构迁移到了 KMP + CMP,实现了 Android/iOS 共享一套代码。这篇文章记录整个迁移过程中的思路、踩坑和最终方案。
more >>如果你手里是一个已经上线很久的 Android 项目,不要把 KMP/CMP 当成“重写项目”的理由。真正可行的路径是:保留现有 Android 业务节奏,把可共享的部分一点点搬到 shared。
迁移可以拆成三步:先迁数据层,再迁状态层,最后才碰 UI。
一开始别追“复用率 80%”。这个目标听上去很美,但会逼着你把不该共享的东西硬塞进 shared,最后两端都难受。
更实用的目标是这三个:
本文以开源项目 HoopsNow 为例,深度拆解 Google 官方推荐的 Now in Android (NIA) 架构在真实项目中的落地实践。涵盖多模块拆分、Convention Plugins、Feature API/Impl 分层、离线优先数据层、Navigation 3 导航以及 Jetpack Compose + MVVM 状态管理等核心主题。
做 Compose 一段时间后,基本都会接触 LocalContext、LocalDensity、LocalLayoutDirection 这些 API。它们背后是同一套机制:CompositionLocal。
在项目里,CompositionLocal 很容易被当成“省参数”的快捷方式。前期写起来很快,后期排查问题时依赖路径会变得不透明。下面这篇按工程视角展开,重点聊三件事:它解决什么问题、什么时候值得用、什么时候更适合参数传递。
做 Android 久了,迟早会碰到这类需求:实时滤镜、相机特效、动态贴纸、复杂转场、海量图元渲染。到这一步,Canvas 和普通属性动画基本就不够用了,OpenGL ES 是绕不开的。
这篇不走“画个三角形就结束”的路线,包含两个 Demo:
两个 Demo 放在一起看,能更直观看到 OpenGL 在 Android 项目里的落地方式,而不只是 API 用法。
more >>大多数用户感知到的卡顿等性能问题的最主要根源都是因为渲染性能。Android系统每隔大概16.6ms发出VSYNC信号,触发对UI进行渲染,如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps,为了能够实现60fps,这意味着程序的大多数操作都必须在16ms内完成。
我们通常都会提到60fps与16ms,可是知道为何会是以程序是否达到60fps来作为App性能的衡量标准吗?这是因为人眼与大脑之间的协作无法感知超过60fps的画面更新。
12fps大概类似手动快速翻动书籍的帧率,这明显是可以感知到不够顺滑的。24fps使得人眼感知的是连续线性的运动,这其实是归功于运动模糊的效果。24fps是电影胶圈通常使用的帧率,因为这个帧率已经足够支撑大部分电影画面需要表达的内容,同时能够最大的减少费用支出。但是低于30fps是无法顺畅表现绚丽的画面内容的,此时就需要用到60fps来达到想要的效果,当然超过60fps是没有必要的。
开发app的性能目标就是保持60fps,这意味着每一帧你只有16ms=1000/60的时间来处理所有的任务。
如果某个操作花费时间是24ms,系统在得到VSYNC信号的时候就无法进行正常渲染,这样就发生了丢帧现象。那么用户在32ms内看到的会是同一帧画面
有很多原因可以导致丢帧, 一般主线程过多的UI绘制、大量的IO操作或是大量的计算操作占用CPU,都会导致App界面卡顿。
一般主线程过多的UI绘制、大量的IO操作或是大量的计算操作占用CPU,导致App界面卡顿。
more >>Crash(应用崩溃)是由于代码异常而导致 App 非正常退出,导致应用程序无法继续使用,所有工作都停止的现象。发生 Crash 后需要重新启动应用(有些情况会自动重启),而且不管应用在开发阶段做得多么优秀,也无法避免 Crash 发生,特别是在 Android 系统中,系统碎片化严重、各 ROM 之间的差异,甚至系统Bug,都可能会导致Crash的发生。
在 Android 应用中发生的 Crash 有两种类型,Java 层的 Crash 和 Native 层 Crash。这两种Crash 的监控和获取堆栈信息有所不同。
more >>应用有三种启动状态,每种状态都会影响应用向用户显示所需的时间:冷启动、温启动与热启动。在冷启动中,应用从头开始启动。在另外两种状态中,系统需要将后台运行的应用带入前台。建议始终在假定冷启动的基础上进行优化。这样做也可以提升温启动和热启动的性能。
more >>
冷启动
- 冷启动是指应用从头开始启动:系统进程在冷启动后才创建应用进程。发生冷启动的情况包括应用自设备启动后或系统终止应用后首次启动。
热启动:
- 在热启动中,系统的所有工作就是将 Activity 带到前台。只要应用的所有 Activity 仍驻留在内存中,应用就不必重复执行对象初始化、布局加载和绘制。
温启动
- 温启动包含了在冷启动期间发生的部分操作;同时,它的开销要比热启动高。有许多潜在状态可视为温启动。例如:
- 用户在退出应用后又重新启动应用。进程可能未被销毁,继续运行,但应用需要执行onCreate() 从头开始重新创建 Activity。
- 系统将应用从内存中释放,然后用户又重新启动它。进程和 Activity 需要重启,但传递到onCreate() 的已保存的实例 state bundle 对于完成此任务有一定助益。
在讨论如何缩减应用的大小之前,有必要了解下应用 APK 的结构。APK 文件由一个 Zip 压缩文件组成,其中包含
构成应用的所有文件。这些文件包括 Java 类文件、资源文件和包含已编译资源的文件。
APK 包含以下目录:
APK 还包含以下文件。在这些文件中,只有 AndroidManifest.xml 是必需的。
resources.arsc :包含已编译的资源。此文件包含 res/values/ 文件夹的所有配置中的 XML 内容。打包工具会提取此 XML 内容,将其编译为二进制文件形式,并压缩内容。此内容包括语言字符串和样式,以及未直接包含在 resources.arsc 文件中的内容(例如布局文件和图片)的路径。
classes.dex :包含以 Dalvik/ART 虚拟机可理解的 DEX 文件格式编译的类。
AndroidManifest.xml :包含核心 Android 清单文件。此文件列出了应用的名称、版本、访问权限和引用的库文件。该文件使用 Android 的二进制 XML 格式。
tag:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent:
meta: false
pages: false
posts:
title: true
date: true
path: true
text: false
raw: false
content: false
slug: false
updated: false
comments: false
link: false
permalink: false
excerpt: false
categories: false
tags: true