新技术层出不穷。作为开发人员,一旦进入这扇门,要么是在学习,要么是在学习的路上。在过去的一年中,最流行的是Flutter和Jetpack-Compose。今天就来说说他们吧。没有具体的想法,想到什么就说什么。另外,整篇文章比较个人化,局限于自己的技术架构。可能会有很多不合适甚至错误的地方。如果您不喜欢它,请不要喷它。如有错误请指正。你想学习新技术吗?有时候真的不是选择题!每当有新技术发布的时候,很多人都会感到一头雾水,所以经常会在技术社区看到:DoyouwanttolearnKotlin?Flutter如何值得学习??有必要去MVVM吗?Jetpack有很多陷阱吗?好像是一道选择题,学习不学习新技术。有一天你会发现,回过头来看,有时候真的不是选择题。只要你还在发展的路上,它就一直在某个路口等着你。学习是必然的选择,你能选择的只是学习的时间节点。就Kotlin而言,前两年可能仍有很多摇摆不定的声音。现在来看,很多官方最新推出的框架,基本上都是用Kotlin写的。对于LiveData和ViewModel,你可能还是会抗拒,继续用Java来写。其实后面也能找到很多。新特性和新写法更多的是结合Kotlin的特性(比如coroutines)。而对于即将问世的稳定版ComposeUI套件,Kotlin成为了你唯一的选择。所以,当谷歌把Kotlin推到Android开发的第一阵营时,它从来没有给你一个新的选择,而只是学习它的时间。这篇文章主要是讲Compose和Flutter,下面主要从各个方面进行分析比较。Compose和Flutter是一道选择题吗?对于Flutter来说,能走多远还不好说,但就目前的情况来看,它已经成功了。对于各种跨平台技术,Flutter作为后来者,现在看来是跨平台的最佳选择。在中国的发展趋势也如火如荼。各大厂商都在研究并将其应用到自己的应用中。很多创业公司甚至以此作为主要开发。毕竟跨平台的优势是不言而喻的。对于Compose,连稳定版都还没有发布,但大家都在翘首以待。那么它们是多项选择题吗?(这里的选择不是指哪一个更好,应该学哪一个,而是是否有必要每一个都单独学习)虽然这个答案没有人敢给你一个定论,但是我可以明确告诉你,他们已经是落后的趋势,未来一定是热点。至于能不能成为主流,就不好说了。个人观点:其实能不能成为主流不是重点。作为一个热点趋势,已经很值得学习了;对于Compose,可以等(也就是等),毕竟不能用于生产环境,需要在实践中验证。就Flutter而言,即使此时开始学习,比别人晚了一点,还在犹豫是否要开始学习,即使是纯技术理论,也值得你去尝试。编程思想的变化从Win32到Web再到Android、iOS,框架通常使用命令式编程风格来完成UI编程,这可能是大多数人最熟悉的风格。随着UI框架的发展,声明式UI编程已经成为趋势。Flutter和Compose作为新推出的UI,自然而然地采用了声明式编程的形式。推出Flutter的意义是一个跨平台的解决方案,而在Android目前的XML-UI编程体系非常完备的情况下,推出Compose的意义何在?先给个个人不负责任的结论:Android上的DeclarativeUI。如果只是因为这个原因,何必浪费时间和精力去做这件事呢?如果你试着从谷歌的角度去思考和解释,就很容易理解了。Android开发的趋势最终会是:整个开发体系趋于统一,主线是响应式编程+声明式UI。假设以上猜想是正确的,那么整个技术框架就清晰了:Kotlin+LiveData+Compose+(其他JetPack功能组件如Room等)。Android的发展一直很混乱。各种MVC、MVP、MVVM,具体到某个架构上也不统一。比如你的MVP可能和我的完全不一样,因为具体的框架大家都懂。它也是不同的。而在具体的代码上,也是如此。你用findViewById(),他用Butterknife,她用Kotlin扩展,我个人用android:onClick="onClickXXX",官方好心推出ViewBinding救火。好心做坏事就像火上浇油。无论哪种方式,都非常不方便。赋值的时候总是需要id和xml布局文件对应,位置不对就更麻烦了。首先要判断是代码问题还是排版问题,代码中可能有多个。对同一个View进行更改,甚至可能将View传递到其他发生更改的地方。一方面,JetPack框架是为开发中的一些点提供更方便、更强大、更简单的解决方案;另一方面是统一整个开发体系。而Compose是这里最重要也是最难的部分。困难有两个方面。一是对于谷歌来说,做这件事的工作是非常繁重和困难的。一方面,完全很难找到好的解决方案。DataBinding可以看作是响应式的一种形式,但是DataBinding并没有脱离xml的布局方式,所以有很多天然的局限性,而为了解决这些局限性,必须做出很多的妥协,这样相应的就增加了使用难度,更何况DataBinding本身也会造成一些性能损失,得不偿失。另一方面,谷歌也很难推出一个全新的UI库。毕竟开发者早已熟悉了固有的形式,很难接受一个陌生的东西。在这方面,也可以看出谷歌做出了很多努力,在稳定版发布之前就已经有不少传道者了。Compose的实现原理我还没有完全接触和研究过,但不管怎么说,在声明式UI方面,在Flutter面前还是只是个小学生。那么到底什么是声明式UI,它的魅力又是什么,下面我们就来说说。先说大家熟悉的命令式,指的是用命令的形式告诉计算机每一步要做什么,才能达到预期的结果。对UI的反应是在不同的时间手动调用或设置每个控件的属性来进行更改以表达当前所需的状态。valtextView=findViewById(R.id.tvHelloWorld)textView.setTextColor(0x123456)textView.setText(statusStr)textView.setOnClickListener{textView.setTextColor(0x654321)textView.setText("clickedstatus")}类似上面的,根据以场景命令的形式,为控件设置不同的属性来进行更改。这样写久了我们不会觉得有什么问题,但实际上会出现很多问题,繁琐且致命:学习成本高,要记住两套知识:一组属性定义在xml中,通过代码动态设置一组属性,因为在大多数情况下,重名是没有意义的,但有时如果不使用百度,很难记住如何动态设置一些属性(例如margin,例如更改svg图标的颜色);繁琐重复效率低:xml中的控件需要在代码中findViewById中的findViewById和变量一一对应,使用的时候需要找到具体的控件变量名,可以更改控件变量在多个角落;有一个致命的隐患:对于控件变量,findViewById的id可能在布局中不存在,或者绑定到其他布局中的控件id,这种错误要等到页面运行时才会暴露出来;同时,控制变量在运行时不知道的情况下随时可以为空,存在空指针的危险。为此,很多对运行时安全性要求高的公司要求在调用控件时,每次都要进行空判断;导致代码逻辑混乱:那么多架构都是为了解决这个问题而设计的,那么declarative是什么意思呢?什么?这个想法是只描述或告诉想要的结果,然后机器会自己弄清楚这个过程。对UI的反应是你只需要声明你想要的界面,不需要手动更新。那么如何在不手动更新的情况下更新界面呢?在使用的时候,我们通常是根据数据显示界面,而数据就相当于我们想要的界面声明,机器只需要根据数据渲染出我们想要的效果即可。.更新时,只需更改数据即可。改变数据就相当于改变了界面语句,此时界面会随着数据的改变而自动更新。这张图很好的描述了declarativeUI的核心思想。简单来说,就是以state为入参,按照写好的构建func,就可以得到我们想要的UI效果。我们使用Flutter代码来实现一个非常相似的接口示例:StatusBeanstatusBean=...;@overrideWidgetbuild(BuildContextcontext){returnTextButton(child:Text("$statusBean",style:TextStyle(color:statusBean.isClick?Colors.red:Colors.white),),onPressed:(){setState((){statusBean.statusStr="clickedstatus";statusBean.isClick=true;});});}分析上面的代码可以看出interface是根据数据statusBean来显示的,statusBean相当于想要的界面声明,点击回调中的setState((){}是告诉程序改变数据后重绘,界面会自动更新根据数据的变化而从上面的代码我们也可以看出原来的xml布局的问题是不存在的,代码中声明性代码更多的工作是考虑控件的反汇编和汇编,以及状态的管理。所以我们从Flutter开源框架中了解到他们中的大多数人都在研究状态管理。不同的路线导致相同的目标。虽然Flutter和Compose有着完全不同的起点和不同的当前目标,但它们的趋势可能归结于一点。先说说它们有多相似,先看看刚才说的declarativeUI:你能看出上面的代码有多相似吗?许多控件在命名和属性方面完全相同。基本上你学了其中一个,另外一个就过半了。虽然开发语言完全不同,但Kotlin和Dart都在Google的控制之下,而Flutter影响了Dart的更新方向。两者都在框架和语言之间深度集成。两种语言在使用形式上也有很多相似之处。Kotlin的coroutine和Dart的async-await,Kotlin的Flow和Dart的eventflow,你会发现在使用形式上有相似之处。而今年更新的Dart是使用了和Kotlin完全一样的形式来支持nullsafety,在使用上也是一模一样的。说到这些,再说点题外话。许多人一直批评Flutter选择Dart作为开发语言。当你真正了解它之后,你会发现这门语言不容小觑,而且这门语言的潜力更大。从上面和Kotlin的对比来看,上面提到的异步和事件流在Dart语言层面是支持的。虽然Dart是一种单线程语言,但它为并发编程提供了一种隔离的天然支持。最近看到了一个关于语言测评的系列文章,感觉比平时编程语言的排名更有价值。有兴趣的也可以看看《现代编程语言终极测评》(这里的链接是翻译链接,英文原文地址没找到)和以后的目标,肯定是一致的。Compose也在往跨平台的方向发展。ComposeforDesktop桌面应用的UI开发支持已经上线,目前处于Alpha阶段。从技术层面来分析这个问题,Compose不能算是Jetpack的UI组件库。它的设计理念和架构本身就具有支持跨平台的能力,而且从介绍上看,它也像Flutter一样采用了Skia渲染,而Skia是Flutter跨平台能力的基石。从开发语言的技术层面来说,Dart具备布局能力不言而喻,而KotlinDSL则完全支持以编程方式构建图形。通过在代码中以声明方式构建图形,这些已在JetPack的导航中列出,也得到了使用。目前ComposeforDesktop已经上线,我觉得下一个很有可能是forWeb。原因当然是分析Kotlin的语言能力。学过Dart的都知道,Dart最初是为了替代JavaScript而设计的,而FlutterforWeb是将Dart直接编译成JavaScript,并将界面的一部分转化为标准的HTML标签,一部分通过Canvas自定义标签转化为绘图,最终形成一个dom树。而且Kotlin还具备转换为JavaScript的能力,这也是Kotlin在早期推广时的一个嘴巴。这篇文章最后的选择就不整理了,最后是关于Flutter和Compose这两个比较流行的相似的UI库。我们最后做个总结。无论是Flutter还是Compose,或者其他优秀的新技术,都相当于我们在开发中使用的武器。您只需要选择适合自己的一款,随手使用即可。但是,新技术之所以受到大家的欢迎和接受,总有它的长处。我们不能总是拘泥于特定的框架和语言。当你还在用小米加步枪的时候,别人已经换成Gad我out了,想象一下。多尝试新事物,不要担心这个新事物后期会怎么样,即使以后不用,至少可以从新事物中学到一些解决问题的新思路,这样你可以理解更多的编程思想。所以,有的时候甚至可以跳出工作需要,去学习一些和你现在的技术栈差异很大的技术或者语言,从而冲击自己的思维禁锢。