0
点赞
收藏
分享

微信扫一扫

Android开发,你所不知道的Android原生开发的现状,android共享元素动画原理

野见 2022-01-20 阅读 74

去年,我编写了一个非常复杂的集成了Parse Server的Android应用。 我使用了Android版本的的Parse SDK,体验都非常好。如果您的公司已经雇用了许多后端开发人员,或者您需要实现许多服务器端逻辑,这可能不是最佳解决方案,但是对于仅在后端执行CRUD操作的初创企业和个人来说,这可能会是一种好的选择。

但是我必须提醒的一点是:如果您要采用数据库即服务的解决方案(例如Firebase),那么请务必了解其长期的成本和影响。

External Storage


关于外部存储的开发,这里有许多有“意思”的事情。

如果您应用的target sdk版本等于或者大于29,那么你的应用将无法再正常访问手机外部存储上的文件,除了少数几种明显的情况。 相反,您需要使用SAF框架(据说),该框架允许用户进行更精细的访问管理。不幸的是,SAF的工作方式与之前完全不同,因此某些应用程序可能需要进行重大重构。

Google希望从Android 10开始对所有的应用程序都实行这一要求,但它引起了开发者社区的强烈抗议,于是他们决定推迟此功能。 因此,即使您的应用设置target sdk版本为 29,它仍可以在“旧版”模式下工作。 但是,无论目标API级别是多少,下一版的Android系统都将对所有应用的存储访问范围做更加严格的限制。

到目前为止,我还没有使用SAF框架,但是从我在互联网上阅读的许多讨论中看来,这可能是一项艰巨的任务。因此,如果您的应用程序还在以“旧版”模式使用外部存储,那么最好立即开始进行重构和测试。

Shared Preferences


几周前,AndroidX系列中添加了一个新框架。 它的commit message是这么说的:

目前我们无需担心,但从长远来看,似乎SharedPreferences会被重写,我们需要使用这种新的方法。

SharedPreferences和这个新框架之间的主要区别在于,默认情况下后者是异步的。 换句话说,您需要实现一个回调以获取特定键的值,该回调将在以后的某个时间收到通知。

如果您对这种异步通知的机制感到好奇,则可以阅读StackOverflow上的这个答案。 Reddit用户Tolriq在这里分享了他们遇到此bug的概率。 在他们的应用中,这个bug会影响1 / 10,000 / SESSIONS_PER_USER_PER_MONTH的用户。 对于一般的应用程序,这可能微不足道。但是在需要高可靠性的情况下,这可能会引起严重的后果。 例如,在装有Android Auto的汽车中,应用程序挂起和随后的崩溃会分散驾驶员的注意力,这可能会导致非常不幸的后果。

Dependency Injection


在依赖注入方面,最大的变化就是Dagger-Android的弃用。 这里我想解释两点: 首先,我说的弃用并不是指“正式”弃用,因为它尚未正式弃用。 其次,Dagger-Android并不是整个Dagger2框架,而只是相对较新的功能。 我在这个主题上写了一篇非常详尽的文章,所以我在这里不再重复。

至于其他依赖注入框架,我不认为它们是Dagger的真正竞争者。 例如,Koin也许不错,但我认为它不会吸引很多人。 实际上,我相信它仅由于两个主要原因而得到了初步采用。 第一个是Dagger的糟糕文档,Koin在这方面要比Dagger领先N光年。 第二个原因是Koin是用Kotlin编写的,它借着kotlin发展的浪潮开始兴起。 到目前为止,这波浪潮已经几乎消逝。

我认为可能会发生的情况是,纯依赖注入的框架(又称为手动依赖注入)会逐渐出现。

现在,谷歌声称“随着应用程序的不断增大,手动依赖项注入成本呈指数增长”。 我认为,这仅表明他们既不了解“指数”的含义,也没做过任何实际的“测量”。 此声明是完全错误的,我希望Google不要以这种方式来误导社区里的开发者了。

事实上,纯依赖注入在后端开发中非常普遍(尤其是在开发微服务的时候,您不想在其中添加对每个服务的框架的依赖),反射也是后端开发中的一个有效的选项。 因此,如果要使用依赖注入框架,他们通常不需要解析编译时代码。

但是,Android开发的情况有所不同。由于我们不能使用反射式DI框架,所以我们使用了Dagg
er。事实上,我们可以使用反射式DI框架,并且对于大多数项目来说都可以,但是却存在性能问题。我并不是说使用反射式DI框架是安全的,但它绝对不是一种非黑即白的方案。无论如何,Dagger已经是在Android开发中使用依赖注入的事实上的标准,我们都使用它。但使用Dagger的代价也很明显:

  • 1)应用的代码越多,在构建过程中运行注解处理所花费的时间就越多。

  • 2)应用参与的开发人员越多,他们需要执行的构建次数就越多。

  • 3)所有开发人员都需要学习Dagger ,这需要很多时间。

换句话说,虽然Dagger确实允许您编写更少的代码,但由于它会影响构建时间和所需的培训时间,因此在大型项目上它会花费更多的时间。

在大型项目中,构建时间慢才是真正的问题,并成为主要的生产力瓶颈。 因此,尽管Dagger确实提供了非常出色的功能来简化DI(当然,一旦您知道如何使用它),但我相信我们对纯依赖注入会产生越来越多的兴趣。

DataBinding


开发人员采用DataBidning的主要原因之一是不再需要调用findViewById()了。 老实说,findViewById确实很冗余,我也不介意摆脱它们。 但是,在我看来,调用findViewById()带来的小麻烦并不能证明使用DataBinding是合理的。 好消息是,很快我们将能够使用另一个新功能ViewBinding来删除这些findViewById()的调用。

实际上,我从来都不相信DataBinding。对于它(应该)解决的问题,我感觉太复杂了。 此外,DataBinding允许开发人员将逻辑放入XML布局中。 经验丰富的开发人员是不会使用这种方法的,因为这增加了项目维护的难度。这是DataBinding框架的另一个缺点。

早在2016年11月,当DataBinding正处于大肆宣传的顶峰时,我在StackOverflow上的一个答案中做出了以下预测:

现在,关于DataBinding的使用率,我没有任何统计数据,但是很明显,它并没有成为行业标准。 我自己还从未见过使用DataBinding的专业项目,也很少见到在其应用中使用DataBinding的开发人员。据我估计,一旦ViewBinding成熟并被广泛采用,DataBinding将会更加流行,并成为“传统”框架。

Preserving State on Configuration Changes


自从引入ViewModel之后,在Android应用中对于配置更改的处理就变得一团糟。 我知道我的这种说法太苛刻了点,但实际上,这是我可以描述的最温和的表达方式。

对我来说幸运的是,Gabor Varadi(又名Zhuinden)已经在Reddit上的这篇文章中对这一问题进行了总结,所以我不需要自己做。他的结论就是:不推荐使用onRetainCustomNonConfigurationInstance(),而推荐使用ViewModel。有趣的是,在该帖子的结尾,Gabor做了一些颇具嘲讽味道的预测:

你发现什么了吗? Retained Fragments现在已经被弃用了! 。

我认为,弃用Retained Fragments实际上是一个好主意。 Fragment的生命周期里具有onAttach()和onDetach()这两个方法的唯一原因就是为了支持Retained Fragments的使用。 通过弃用Retained Fragments,这些方法也可以弃用,并且可以简化Fragment的生命周期。 如果您使用我的方法来处理Fragment的生命周期,那么这种弃用就不会让您感到困扰,因为我长期以来一直建议您避免Retained Fragments,忽略onAttach()和onDetach()方法。

尽管有充分的理由要弃用Retained Fragments,但弃用onRetainCustomNonConfigurationInstance()却是胡说八道。 这不是我说的,而是Jake Wharton说的(您可以在前面提到的Gabor在Reddit上的帖子下阅读他的原话)。

为什么要做这些变动呢?我只能看到一种解释:Google决定不管其它技术优势如何,都强制将所有Android项目迁移到ViewModel。 他们愿意弃用所有现有的替代方案以实现其目标,即使这些替代方案实际上优于ViewModel本身。

听起来有点阴谋吧? 我同意。 但是,幸运的是,我们可以对此理论有一个简单的检验。

虽然我不喜欢Preserving State on Configuration Changes,但它不会以任何方式影响我,因为我没有使用它。 实际上,绝大部分应用程序都不需要它。 它们也不需要ViewModel。正确处理Configuration Changes的方式就是在onSaveInstanceState(Bundle)回调方法里增加处理逻辑。 这是一种更简单,更好的方法,因为它还可以处理保存和恢复流程(也称为进程终止)。 因此,只要我能以这种方式保存状态,就可以了。 尽管Google进行了大量的营销和公关工作,但许多经验丰富的开发人员都意识到ViewModel太复杂了,并且有更好的方法来保留配置更改的状态。

因此,如果Google确实有别有用心,并且想迫使所有项目都使用ViewModel,那么他们还需要弃用onSaveInstanceState(Bundle)。 我知道这听起来很疯狂,但这实际上是件好事,因为如果这种疯狂的预测成真,您就会知道基础理论是正确的。

但是,鉴于Android的内存管理机制,Google不能仅在不提供可靠替代方案的情况下就弃用onSaveInstanceState(Bundle)。 “幸运”的是,这些变化已经应用在ViewModel的保存状态模块上了。

我想在一两年内我们就会知道这种做法是否有任何优点。‘

总而言之,正如我在本节开头所说的那样,自ViewModel发布以来,Android中的Configuration Changes就成了屎。 两年多以前,当我撰写题为“Android ViewModel Architecture Component Considered Harmful”的文章时,我预测ViewModels将是一种浪费。我的所有预测都是真实的,但不幸的是,事实证明真相比这还糟。

Concurrency


在并发这方面,最大的变化就是AsyncTask的弃用。 我已经写了一篇有关此主题的非常详细的文章,并提出了具体建议,因此在此不再赘述。

接下来我说的话可能会使部分读者感到不满。拜托,别太把这事当真。

Android开发中另一个流行的多线程框架RxJava很快就会成为“过去式”。 从下面这幅StackOverflow趋势图可以明显看出:

许多开发者会质疑我的观点,称该数据不具有代表性,并且还有其他方法的可以解释该图。他们可能是正确的,因为我自己也不是数据科学家。但是,在此图中,我看不到任何其他关于峰值的解释,而且RxJava的曲线与AsyncTask的曲线具有相同的斜率。

因此,如果您尚未花时间在学习RxJava上并且您的项目没有使用它,那么我建议您避免使用它。实际上,这一直是我的建议,今天它也得到了数据的支持。

如果您的项目已经使用了Rx,也请不要惊慌,您无需立即重构任何东西。但是,请记住,今后找到具有Rx经验的开发人员将越来越困难。 因此,在项目中广泛使用Rx可能需要新的开发人员投入更多的时间。最终,广泛使用Rx的项目将被视为“not cool”(例如今天使用AsyncTask和Loaders的项目)。

我知道我的这些观点对于许多开发人员来说很不友好。他们花了数周时间来学习RxJava,甚至说服了同事在项目中使用RxJava,现在我却说它会成为“过去式”。我只想说我只是分析实际情况并根据我所看到的做出预测,我可能是错的,也可能是对的。

在Kotlin语言中,我们可以使用协程。我最近使用协程实现了一些复杂的用例,发现此框架非常的细微和复杂,并且相对不成熟,我甚至发现了一个bug。

有一种流行的说法是,协程使得并发处理更简单。我从来不这样认为,因为我知道并发是非常复杂的,但是在我有了一些实践经验之后,我可以自信地说,协程并没有想像中的那么美好。在我看来,协程实际上增加了程序复杂性,所以我建议你们小心地使用它们。

另一方面,协程似乎将成为Kotlin语言里处理并发操作的默认方式。因此,我认为如果您编写Kotlin代码,您需要投入时间并学会使用它们。

据我所知,目前还有一个流式框架,它在协程之上添加了流处理操作符。几个月前才稳定下来,所以我现在还不能说什么。

Kotlin


现在让我们来讨论一下Kotlin。根据以往的经验,我知道这是一个非常敏感的话题,而且不管我描述的多么客观,最终都会遭受一些开发者的攻击。然而,我认为在总结原生Android开发现状的时候跳过Kotlin是极不诚实的。因此,我再次请你不要把我说的话当真。

你所需要知道的一个重要的事实是:在Android开发中使用Kotlin会严重增加你的构建时间。

在这篇文章中,您会了解到我在使用Kotlin进行开发时对构建时间所进行的统计测试的结果。clean build 增加了18%的构建时间,incremental build 增加了8%的构建时间。

Uber与JetBrains也联合发表了他们自己的研究结果,他们的结果更为负面。如果您不在应用程序中使用注解处理器,那么引入Kotlin可能会使您的构建时间增加四倍!如果您使用了注解处理器,那么引入Kotlin会使您的构建时间增加50%-100%。

Uber的研究结果与将OkHttp迁移到Kotlin版本后构建时间增加了4倍的结果是一致的。

如果您对这些数字感到惊讶,您不用担心-这不是您的错,而且您并不孤单。尽管这个事实极为重要,但它并未得到广泛讨论,并且我觉得Google也试图回避这个事实。我曾与Google内部一个熟悉此事的开发人员有过一次非常有趣的讨论,我问他是否可以讨论下这个话题,他说:“我不喜欢;我不喜欢;我不喜欢。这是一件很微妙的事情。”

除了增加构建时间之外,Kotlin还不支持增量注解处理,而在大约10个月前Java就已经支持增量注解处理了。

两年前,我写了一篇文章来警告开发者们在早期使用Kotlin时可能会遇到的潜在风险。在很长一段时间内我被称为“kotlin的讨厌者”。

但是,如果您今天阅读这篇文章,您会发现我实际上低估了这些问题的严重性。在大型的Android项目上,构建时间是最糟糕的生产力杀手之一,而且即使在今天,即Kotlin被官方“正式采用”两年多之后的今天,Kotlin仍然不如Java。不管Kotlin带来什么其他好处,所有这些都可能由于更长的构建时间而被否定。

也就是说,我们不应改忽视这样一个事实:是谷歌将android开发的生态强行推向了kotlin,使得其使用率在稳步上升。

就我个人而言,我并没有在我目前已经开始的新项目中选择kotlin语言,我不想在kotlin上浪费我自己的时间。不过,从现在开始,我会认真考虑使用kotlin来开发新项目,我已经在几个demo上尝试过了。但是我不同意开发人员说你必须在新项目中使用Kotlin,这仍然是一种权衡。

至于你们是否应该将现有项目迁移到Kotlin,我无法提供任何一般性建议,您需要根据具体的情况进行仔细的分析。但是,如果您确实决定开始(或已经开始)迁移,那么这个帖子可能会对您有用。

是谷歌将android开发的生态强行推向了kotlin,使得其使用率在稳步上升。

就我个人而言,我并没有在我目前已经开始的新项目中选择kotlin语言,我不想在kotlin上浪费我自己的时间。不过,从现在开始,我会认真考虑使用kotlin来开发新项目,我已经在几个demo上尝试过了。但是我不同意开发人员说你必须在新项目中使用Kotlin,这仍然是一种权衡。

至于你们是否应该将现有项目迁移到Kotlin,我无法提供任何一般性建议,您需要根据具体的情况进行仔细的分析。但是,如果您确实决定开始(或已经开始)迁移,那么这个帖子可能会对您有用。

举报

相关推荐

0 条评论