emo-scheme 新特性

缘起

最近发现 scheme 组件使用的一些不完美和可改进点,主要有以下几个:

  1. DeepLink 该如何支持?
  2. 期望使用时可以获取结构化的数据(data class),避免从 NavBackStackEntrygetStringgetInt 之类的。
  3. 期望有更好的转场动画支持。

对于 DeepLink 而言,因为 scheme 本来就是 uri 的结构,所以我建议的方案是用一个透明的 Activity 做中转,把 protocolhost 部分一下,就是可以用来接入 scheme 框架了,所以本文不做过多分析。

所以最新更新的 0.8.0 主要是为了解决传参结构化和转场动画问题。

结构化传参与解析

目前 scheme 提供的传参方式主要是 Bundle 式的原始方案:在传参需要使用 schemeBuilder.arg(name, value) 的形式链式拼接,而使用时则需要从 NavBackStackEntryarguments 中去一个个的取出来,所以这里存在 name 的管理,而且你还需要记住不同的 name 对应的 value 的类型

@ComposeScheme(action = SchemeConst.ACTION_HOME,alternativeHosts = [HomeActivity::class]
)
@Composable
fun HomePage(navBackStackEntry: NavBackStackEntry) {val a = navBackStackEntry.arguments?.getString("nameA")val b = navBackStackEntry.arguments?.getInt("nameB")
}

而结构化传参则期望我传递给 Composable 函数的就是结构化的数据

@ComposeScheme(action = "action",alternativeHosts = [MainActivity::class]
)
@Composable
fun SchemeModelPage(arg: DataArg){ 
}

因为我们参数会以 url query 的形式传递,实际上我们就需要实现一个 Encode/Decode 的过程。

要实现这个方案,我们有两种选择:

  1. 反射:Encode 通过反射得到 class 下的所有字段名和值,来拼接字符串。Decode 通过将字符串解析成 Map, 再反射赋值给 class
  2. 代码生成:通过 ksp 为每个 class 生成相应的 Encode/Decode 方法实现

为了性能考虑,一般我们会选择代码生成的方案,不过我们并不需要从零开始去设计一套方案,因为我们已经有了强大的 kotlin-serialization。 因为这本身也是一个序列化反序列化的过程,只不过我们这里只是序列化成了 url query 的形式。大家一般都是用了 kotlin-serialization-json 来做 json 的序列化,其实大家不知道是它还可以被序列化成 protobufcbor 等形式,抽象是做得相当好的了。

使用

首先,定义参数类

// 只支持 bool,int,long,float,string 这几个类型
// 可以享受 Kotlin 的默认值
@Serializable
data class DataArg(val i: Int = 3,val l: Long = 4,val b: Boolean = true,val str: String = "xixi"
)

scheme 构建可以从参数类中构建

val arg = DataArg(str = "hehe")
// 通过传递给 SchemeBuilder 的 model 来构建 scheme
val scheme = schemeBuilder.model(arg).toString()

然后就可以在 Composable 方法上直接使用了

@ComposeScheme(action = "action",alternativeHosts = [MainActivity::class]
)
@Composable
fun SchemeModelPage(arg: DataArg){ // 直接将参数类传递给 Composable 函数就行}

如果你需要使用到 NavBackStackEntry, 那也可以写到方法里


@ComposeScheme(action = "action",alternativeHosts = [MainActivity::class]
)
@Composable
fun SchemeModelPage(navBackStackEntry: NavBackStackEntry, arg: DataArg){ // 注意顺序不能变更}

当然你可以不使用这一特性,旧版本的工作方式依旧能正常工作。

异常处理

由于引入了序列化与反序列化,就有一些更多不可控的因素。例如使用了 scheme 不支持的类型,如列表等。还有反序列化失败等。

如果有异常那就崩溃,那体验就不好了。 如果把异常全都吞掉,那开发查问题就太难了。所以这里关键倚靠的是 EmoConfig.debug 的值了:

  • 如果值为 true, 那就会直接抛出异常,直接 crash
  • 如果值为 false, 那就会吞掉异常,具体表现为:
    • 如果是从参数类中构建 scheme 时失败了,那这个 scheme 不会触发跳转。
    • 如果从 scheme 中解析参数类失败了,那就视 Composable 函数签名而定了: 如果 Composable 函数指定参数可空 即声明为 fun SchemeModelPage(arg: DataArg?),则函数获得的实参为 null,交给开发者自己去处理这种情况;如果声明了不可空,则 Composable 函数不会被调用,用户侧可能就看到白屏了。

动画

scheme 框架底层依赖的是 accompanistNavigation 库,其本身就有提供高度自定义化的动画支持。其函数签名为:

public fun NavGraphBuilder.composable(route: String,arguments: List<NamedNavArgument> = emptyList(),deepLinks: List<NavDeepLink> = emptyList(),enterTransition: (AnimatedContentScope<NavBackStackEntry>.() -> EnterTransition?)? = null,exitTransition: (AnimatedContentScope<NavBackStackEntry>.() -> ExitTransition?)? = null,popEnterTransition: (AnimatedContentScope<NavBackStackEntry>.() -> EnterTransition?)? = enterTransition,popExitTransition: (AnimatedContentScope<NavBackStackEntry>.() -> ExitTransition?)? = exitTransition,content: @Composable AnimatedVisibilityScope.(NavBackStackEntry) -> Unit
)

其就包括了 enterexitpopEnterpopExit 四个动作场景的动画,在旧版本,虽然有提供动画自定义,但是将原本的功能给阉割了部分,而新版本虽然使用上不算完美,但保留了其全部自定义的能力。

基础知识

如果我们使用过 Fragment,那么你肯定对动画的这四个动作很熟悉。但是,两者的名字相同,但代表的意义并不一致。

Fragment 启动一个新的界面,是开启了一个事务,然后在这个事务中,规定新旧界面的动画, 假设有界面 AB

  • A 切换到 B, 对 B 应用 enter, 对 A 应用 exit
  • B 返回到 A, 对 B 应用 popExit, 对 A 应用 popEnter

简单记忆就是 1,4 参数应用新界面, 2,3参数应用旧界面。

但是到了 Compose 情况就不一样了,Compose 是声明式,用状态描述一切,composable 是为当前声明注册了四个动画描述,用于在不同状态切换时使用不同动画,所以这四个动画都只与注册的 Composable 函数相关。所以:

  • A 切换到 B, 对 B 应用 Benter, 对 A 应用 Aexit
  • B 返回到 A, 对 B 应用 BpopExit, 对 A 应用 ApopEnter

因为动画是提前注册好的,所以会存在一个问题,例如 A 可能跳转 B, 也可能跳转 C, 那么跳转时都是应用 Aexit, 那我如果期望一个使用 slide 动画,一个使用 fade 动画该怎么办呢?

仔细观察上面函数的签名,就会发现我们注册时注册的不是动画本身,而是要求传入一个 lambda 函数,其函数的返回值才是动画。所以我们是在不同场景都重新构一个动画,那具体的场景我们该怎么区分呢?

答案就存在这个 lambda 函数是在 AnimatedContentScope<NavBackStackEntry> 域下执行的,这个可以拿到动画 initialStatetargetState,具体而言就是新旧界面的 NavBackStackEntry。 如此就可以根据其做出区分。

其实在原本框架上,NavBackStackEntry 的区分能力还是一般,但是如果使用 scheme 框架的话,那就可以拿到更多的区分信息

// 拿到 scheme
fun NavBackStackEntry.readOriginScheme()
// 拿到 scheme transition 的声明,具体含义可见下一节
NavBackStackEntry.readTransition()
// 拿到 scheme 的 action
fun NavBackStackEntry.readAction()

通过这些信息,我们就可以执行丰富的判断。

在了解了这长长的基础后,我们就可以来看看在 scheme 的注解下,该怎么自定义动画。

scheme 转场动画使用

注解 ActivitySchemeComposeScheme 都有一个字段叫 transition, 其类型是 int, 指明使用哪一个 SchemeTransitionProvider,框架提供了几个默认实现:

  • SchemeTransition.PUSH: 常规模式,从右边进入, iOS 式命名
  • SchemTransition.PRESENT: 从底部升起, iOS 式命名
  • SchemTransition.SCALE: 缩放进入
  • SchemTransition.PUSH_THEN_STILL: 从右边进入,exitpopEnter 保持静止,如果从当前界面去往其它界面会有非 push 行为,那么就需要使用这个或者完全自定义。

如果你有自定义需求,那么可以往 SchemeTransitionProviders 中注册新的类型与实现

object SchemeTransitionProviders{// 开发者注册的 type 需要大于 0fun put(type: Int, provider: SchemeTransitionProvider)fun get(type: Int): SchemeTransitionProvider
}

SchemeTransitionProvider 是我们自定义需要实现的接口:

interface SchemeTransitionProvider {// 当以 `activity` 进入时需要提供的资源fun activityEnterRes(): Intfun activityExitRes(): Intfun enterTransition(): (AnimatedContentScope<NavBackStackEntry>.() -> EnterTransition?)?fun exitTransition(): (AnimatedContentScope<NavBackStackEntry>.() -> ExitTransition?)?fun popEnterTransition(): (AnimatedContentScope<NavBackStackEntry>.() -> EnterTransition?)?fun popExitTransition(): (AnimatedContentScope<NavBackStackEntry>.() -> ExitTransition?)?
}

需要说明的是,因为我的 scheme 是支持 ActivityCompose 各种搭配乱跳的,所以需要提供 activity 的转场动画,但它是事务型的,是服务于新旧两个界面的。

而其它的几个方法,详细在了解了上一节的基础知识后,也都了解了具体是做什么的了。

那为何说是不那么完美的呢?

其实最好的写法是直接在 ComposeSchemeActivityScheme 中指明 SchemeTransitionProvider, 例如

@ComposeScheme(action = "action",alternativeHosts = [MainActivity::class],transition = PushSchemeTransitionProvider::class,
)
@Composable
fun SchemeModelPage(navBackStackEntry: NavBackStackEntry, arg: DataArg){ // 注意顺序不能变更}

这样就不需要再搞一个 int ,然后去注册了。

那为何没有用这种形式呢? 主要是因为 SchemeTransitionProvider 依赖了 AnimatedContentScopeNavBackStackEntry,而它们又不是纯粹的 java 库,在 ksp 库中无法引入,或者有实现方案,但是我不知道?如果有了解的,欢迎交流。 我也可以用 KClass<*>,不指明类型,运行时再检查,就像上面 alternativeHosts 做的那样,但是问题就是无法写默认值,每写一个界面就指定一个 transition, 也有点蛋疼。所以目前我采取的这种注册式的折中方案。

最后

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

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
在这里插入图片描述
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

全套视频资料:

一、面试合集

在这里插入图片描述
二、源码解析合集
在这里插入图片描述

三、开源框架合集
在这里插入图片描述
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单测时尽量用fake object

1. 单元测试的难点&#xff1a;外部协作者(external collaborators)的存在 单元测试是软件开发的一个重要部分&#xff0c;它有助于在开发周期的早期发现错误&#xff0c;帮助开发人员增加对生产代码正常工作的信心&#xff0c;同时也有助于改善代码设计。**Go语言从诞生那天起…

【从零开始玩量化20】BigQuant平台策略代码本地化(与Github同步)

引言 最近发现了个不错的量化平台&#xff0c;BigQuant BigQuant的客服找到我&#xff0c;推荐他们平台给我使用&#xff0c;宣传的是人工智能&#xff0c;里面可以使用类似ChatGPT的聊天机器人&#xff0c;和可视化拖拉拽功能实现策略。 不过&#xff0c;这些都是锦上添花的…

微软“封杀”了推特,马斯克怒了:我要起诉微软!

文&#xff5c;鱼羊 发自 凹非寺源&#xff5c;量子位 OpenAI还没撕完&#xff0c;马斯克又跟微软杠上了&#xff0c;甚至直接在推特上放话&#xff1a; 我要告微软&#xff01; 这又是发生了甚么&#xff1f; 原因无它&#xff1a;微软刚刚“封杀”了推特。公告显示&#xff0…

新 Bing 惨遭微软“脑叶切除”,引大量网友不满!

整理 | 禾木木 责编 |梦依丹 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 在新版 Bing 引入 ChatGPT 爆火之后&#xff0c;Bing 就开始了各种“作妖”秀&#xff0c;翻车离谱事件是一件接着一件。有不少用户表示在和 Bing 的交流过程中&#xff0c;发现…

成为钢铁侠!只需一块RTX3090,微软开源贾维斯(J.A.R.V.I.S.)人工智能AI助理系统

梦想照进现实&#xff0c;微软果然不愧是微软&#xff0c;开源了贾维斯(J.A.R.V.I.S.)人工智能助理系统&#xff0c;贾维斯(jarvis)全称为Just A Rather Very Intelligent System&#xff08;只是一个相当聪明的人工智能系统&#xff09;&#xff0c;它可以帮助钢铁侠托尼斯塔克…

【JAVA】让 ChatGPT 来描述 IOC

前言 又迎来了一年一度的金三银四&#xff0c;虽然说今年的大环境不好&#xff0c;但是招聘还是在火热进行中。 面试过 Java 工程师的小伙伴都知道&#xff0c;Spring 中的 IOC 是面试高频题&#xff0c;面试官上来就问&#xff0c;知道什么是 IOC 吗&#xff0c;IOC 是如何初…

【工具】VScode|Linux 中怎么调试 Python 项目比较方便?又名 VScode 怎么调试 Python 项目(兼容环境Ubuntu18.04)

使用过 Anaconda、Jupyter、Pycharm、VScode、VS2022、pdb 这几个 IDE 去编写 python 项目或者维护 python 环境&#xff0c;各有各的优缺点&#xff0c;但 VScode yyds&#xff01; 可能会被网上说得天花乱坠的 Python 配置项吓退&#xff0c;会被 VScode 各种插件介绍吓退&a…

日本僧人问道弘法寺当家师

时间过得真快&#xff0c;六名日本禅僧在弘法寺为期10天的体验生活已进行到第三天&#xff0c;晚上10&#xff1a;00&#xff0c;方丈印顺大和尚依然等候在丈室&#xff0c;与前二日不同的是&#xff0c;弘法寺的当家师智空法师也来到了方丈室。 六位日本僧人行礼完…

佛教基础知识

佛教基础知识 1、《佛教常识》&#xff08;1&#xff09;佛陀和佛教的创立&#xff08;2&#xff09;佛法的基本内容、书籍&#xff08;3&#xff09;僧团和佛的弟子&#xff08;4&#xff09;佛教在印度的发展、衰亡及复兴&#xff08;5&#xff09;佛教在中国的发展、演变 2、…

【ChatGPT与网络安全攻击】AI密码破解器可在60秒内攻破50%以上普通密码

研究表明&#xff0c;ChatGPT等功能强大AI工具已经被用于网络攻击者实施犯罪活动&#xff0c;例如开发恶意软件和生成钓鱼邮件等。如果人们的密码从数据库泄露或被破坏&#xff0c;那么网络攻击者采用AI密码破解器猜出密码是概率几乎是100%&#xff0c;其中50%以上会在60秒内被…

chatgpt赋能Python-pythonmd5解密

Python MD5解密原理及应用 MD5是一种广泛使用的哈希算法&#xff0c;被用于加密敏感数据。MD5算法使用不可逆的方法将任何长度的数据转换为固定长度的哈希值&#xff0c;并且只能通过暴力破解的方式破解加密后的敏感数据。尽管MD5算法被广泛采用&#xff0c;但历史上已发现其存…

chatgpt赋能python:Python怎么破解Windows软件?

Python怎么破解Windows软件&#xff1f; 作为一名有10年Python编程经验的工程师&#xff0c;我想分享一些破解Windows软件的经验。Python是一种高级编程语言&#xff0c;可以用于许多不同的应用程序&#xff0c;包括软件破解。 什么是软件破解&#xff1f; 软件破解是指绕过…

讯飞星火认知大模型与ChatGPT的对比分析

引言&#xff1a; 人工智能是当今科技领域的热门话题&#xff0c;自然语言处理是人工智能的重要分支。自然语言处理的目标是让计算机能够理解和生成自然语言&#xff0c;实现人机交互和智能服务。近年来&#xff0c;随着深度学习的发展&#xff0c;自然语言处理领域出现了许多创…

【Unity开发小技巧】UnityWebGL移动端和电脑端调起输入法,中文输入处理

目录 一.TextMesh Pro中文显示问题 1.PC端和移动端中文显示异常乱码&#xff08;解决方案&#xff09; 1.制作TextMesh Pro字体 方式一 2.制作TextMesh Pro字体 方式二 3.通用字体资源 2.web端中文不能输入窗口模式&#xff08;解决方案&#xff09; 二.移动端Inputfile调…

分享一个利用ChatGPT为世界上任何城市建立旅行路线(带链接)的工具 GPTravel Advisor

GPTravel Advisor - 在几秒钟内创建世界上任何城市的旅行路线 网址链接&#xff1a;https://gpt-travel-advisor.vercel.app/ GIthub&#xff1a;https://github.com/dabit3/gpt-travel-advisor ChatGPT中文论坛&#xff1a;https://gptocean.com/

ChatGPT 新版 API 推出 語音轉換文字模型 Whisper

OpenAI 宣布釋出新 ChatGPT API&#xff0c;允許第三方開發人員通過 API 將 ChatGPT 整合到他們的網站、應用程式及產品中。同時發表開源的&#xff0c;讓用户用以轉錄或翻譯音訊。 OpenAI 表示&#xff0c;新版的 ChatGPT API 不僅可用於創建人工智能聊天界面&#xff0c;更可…

怎么玩chatgpt?如何利用ChatGPT来编写PRD?

很多人对于chatgpt不知道怎么玩&#xff1f;其实对于一个产品经理来说&#xff0c;他可以这样玩&#xff01;在产品开发过程中&#xff0c;产品需求文档&#xff08;PRD&#xff09;是一个非常重要的文档&#xff0c;它描述了产品的功能、特性和目标用户等信息。编写PRD需要耗费…

我群 300+人已熟练使用的 ChatGPT Prompt 技巧

这是吴恩达联合 OpenAI 官方录制的 ChatGPT Prompt 免费视频课&#xff0c;最后一个总结&#xff0c;视频&#xff1a; https://learn.deeplearning.ai/chatgpt-prompt-eng/lesson/2/guidelines 在这一节中&#xff0c;我会分享两个技巧&#xff1a;Transforming 和 Expanding …

利用python进行数据分析~基金分析

利用python进行基金数据分析 背景说明分析过程1.获取所有种类基金数据1.1导入相关包1.2通过天天基金网接口获取基金数据1.2.1获取网页信息1.2.2将数据转化成二维表并写入本地磁盘&#xff08;dataframe&#xff09; 1.3数据概览1.3.1查看前几行数据1.3.2查看各类型基金分布及可…

Tushare+Talib基金指标分析

本文介绍python语言下的两个第三方库&#xff0c;Tushare&#xff08;获取股票和基金数据&#xff09;和Ta-Lib&#xff08;用于数据指标分析&#xff09;&#xff0c;及其相关使用案例。 一、安装 Tushare安装 # 方式1&#xff1a;pip install tushare# 如果安装网络超时可尝…