Follow feeds: blogs, news, RSS and more. An effortless way to read and digest content of your choice.
Get Feederxuyisheng.top
Get the latest updates from DoctorXu directly as they happen.
Last updated almost 4 years ago
almost 4 years ago
人们经常忽略Iterable和Sequence之间的区别。这是可以理解的,因为即使它们的定义也几乎是相同的。interface Iterable<out T> { operator fun iterator(): Iterator<T&gt } interface Sequence<out T>...
almost 4 years ago
Kotlin对集合操作类新增了很多快捷的高阶函数操作,各种操作符让很多开发者傻傻分不清,特别是看一些Kotlin的源码或者是协程的源码,各种眼花缭乱的操作符,让代码完全读不下去,所以,本文将对Kotlin中的集合高阶函数,进行下讲解,降低大家阅读源码的难度,下面看几个用的比较多的高阶函数使用。首先是sumOf,作为一个很方便的求和函数,它可以快速对集合内的某些参数进行sum操作,代码如下所示。val list = mutableListOf(1, 2, 3, 4) val sumOf = list.sumOf {...
almost 4 years ago
在Android中,Handler是一个使用的非常频繁的东西,输入事件机制和系统状态,都通过Handler来进行流转,而在Handler中,有一个很少被人提起但是却很有用的东西,那就是IdleHandler,它的源码如下。/** * Callback interface for discovering when a thread is going to...
about 4 years ago
如果要在Android系统中找一个一直存在,但一直被人忽略,而且有十分好用的功能,那么Widget,一定算一个。这个从Android 1.x就已经存在的功能,经历了近10年的迭代,在遭到无数无视和白眼之后,又重新回到了大家的视线之内,当然,也有可能是App内部已经没东西好卷了,所以大家又把目光放到了App之外,但不管怎样,Widget在Android 12之后,都开始焕发一新,官网镇楼,让我们重新来了解下这个最熟悉的陌生人。https://developer.android.com/develop/ui/views/appwidgets/overviewWidget使用的是RemoteView,这与Notification的使用如出一辙,RemoteView是继承自Parcelable的组件,可以跨进程使用。在Widget中,通过AppWidgetProvider来管理Widget的行为,通过RemoteView来对Widget进行布局,通过AppWidgetManager来对Widget进行刷新。基本的使用方式,我们可以通过一套模板代码来实现,在Android Studio中,直接New Widget即可。这样Android Studio就可以自动为你生成一个Widget的模板代码,详细代码我们就不贴了,我们来分析下代码的组成。首先,每个Widget都包含一个AppWidgetProvider。这是Widget的逻辑管理类,它继承自BroadcastReceiver,然后,我们需要在清单中注册这个Receiver,并在meta-data中指定它的配置文件,它的配置文件是一个xml,这里描述的是添加Widget时展示的一些信息。从这些地方来看,其实Widget的使用还是比较简单的,所以本文也不准备来讲解这些基础知识,下面我们针对开发中会遇到的一些实际需求来进行分析。appwidget-provider配置文件这个xml文件虽然简单,但还是有些有意思的东西的。尺寸在这里我们可以为Widget配置尺寸信息,通过maxResizeWidth、maxResizeHeight和minWidth、minHeight,我们可以大致将Widget的尺寸控制在MxN的格子内,这也是Widget在桌面上的展示方式,它并不是通过指定的宽高来展示的,而是桌面所占据的格子数。官方设计文档中,对格子数和尺寸的转换标准,有一个表格,如下所示。我们在设计的时候,也应该尽量遵循这个尺寸约束,避免在桌面上展示异常。在Android12之后,描述文件中,还增加了targetCellWidth和targetCellHeight两个参数,他们可以直接指定Widget所占据的格子数,这样更加方便,但由于它仅支持Android12+,所以,通常这些属性会一起设置。有意思的是这个尺寸标准并不适用于所有的设备,因为ROM的碎片化问题,各个厂商的桌面都不一样,所以。。。只能参考参考。updatePeriodMillis这个参数用于指定Widget的被动刷新频率,它由系统控制,所以具有很强的不定性,而且它也不能随意设置,官网上对这个属性的限制如下所示。updatePeriodMillis只支持设置30分钟以上的间隔,即1800000milliseconds,这也是为了保证后台能耗,即使你设置了小于30分钟的updatePeriodMillis,它也不会生效。对于Widget来说,updatePeriodMillis控制的是系统被动刷新Widget的频率,如果当前App是活着的,那么随时可以通过广播来修改Widget。而且这个值很有可能因为不同ROM而不同,所以,这是一个不怎么稳定的刷新机制。其它除了上面我们提到的一些属性,还有一些需要留意的。resizeMode:拉伸的方向,可以设置为horizontal|vertical,表示两边都可以拉伸。widgetCategory:对于现在的App来说,只能设置为home_screen了,5.0之前可以设置为锁屏,现在基本已经不用了。widgetFeatures:这是Android12之后新加的属性,设置为reconfigurable之后,就可以直接调整Widget的尺寸,而不用像之前那样先删除旧的Widget再添加新的Widget了。配置表这个配置文件的主要作用,就是在添加Widget时,展示一个简要的描述信息,所以,一个App中是可以存在多个描述xml文件的,而且有几个描述文件,添加时,就会展示几个Widget的缩略图,通常我们会创建几个不同尺寸的Widget,例如2x2、4x2、4x1等,并创建多个xml面试文件,从而让用户可以选择添加哪一个Widget。不过在Android12之后,设置一个Widget,通过拉动来改变尺寸,就可以动态改变Widget的不同展示效果了,但这仅限于Android12+,所以需要权衡使用利弊。configure通过configure属性可以配置添加Widget时的Configure Activity,这个在创建默认的Widget项目时就已经可以选择创建了,所以不多讲了,实际上就是一个简单的Activity,你可以配置一些参数,写入SP,然后在Widget中进行读取,从而实现自定义配置。应用内唤起Widget的添加页面大部分时候,我们都是通过在桌面上长按的方式来添加Widget,但是在Android API 26之后,系统提供了一直新的方式来在应用内唤起——requestPinAppWidget。文档如下。https://developer.android.com/reference/android/appwidget/AppWidgetManager#requestPinAppWidget(android.content.ComponentName, android.os.Bundle, android.app.PendingIntent)代码如下所示。fun requestToPinWidget(context...
about 4 years ago
设置系统壁纸这个功能,对于应用层App来说,场景其实并不多,但在一些场景的周边活动中,确也是一种提升品牌粘性的方式,就好比某个活动中创建的角色的壁纸美图,这些就可以新增一个设置壁纸的功能。从原始的Android开始,系统就支持设置两种方式的壁纸,一种是静态壁纸,另一种是动态壁纸。静态壁纸静态壁纸没什么好说的,通过系统提供的API一行代码就完事了。最简单代码如下所示。val wallpaperManager = WallpaperManager.getInstance(this) try { val bitmap = ContextCompat.getDrawable(this, R.drawable.ic_launcher_background)?.toBitmap() wallpaperManager.setBitmap(bitmap)...
about 4 years ago
Flutter的图片系统基于Image的一套架构,但是这东西的性能,实在不敢恭维,感觉还停留在Native开发至少5年前的水平,虽然使用上非常简单,一个Image.network走天下,但是不管是解码性能还是加载速度,抑或是内存占用和缓存逻辑,都远远不如Native的图片库,特别是Glide。虽然Google一直在有计划优化Flutter Image的性能,但现阶段,体验最佳的图片加载方式,还是通过插件,使用Glide来进行加载。所以,在混编的大环境下,将Flutter的图片加载功能托管给原生,是最合理且性能最佳的方案。那么对于桥接到原生的方案来说,主要有两个方向,一个是通过Channel来传递加载的图像的二进制数据流,然后在Flutter内解析二进制流后来解析图像,另一个则是通过外接纹理的方式,来共享图像内存,显然,第二种方案是更好的解决方案,不管从内存消耗还是传输性能上来说,外接纹理的方案,都是Flutter桥接Native图片架构的最佳选择。虽然说外接纹理方案比较好,但是网络上对于这个方案的研究却不是很多,比较典型的是Flutter官方Plugins中的视频渲染的方案,地址如下所示。https://github.com/flutter/plugins/tree/main/packages/video_player这是我们研究外接纹理的第一手方案,除此之外,闲鱼开源的PowerImage,也是基于外接纹理的方案来实现的,同时他们也给出了基于外接纹理的一系列方案的预研和技术基础研究,这些也算是我们了解外接纹理的最佳途径,但是,基于阿里的一贯风格,我们不太敢直接大范围使用PowerImage,研究研究外接纹理,来实现一套自己的方案,其实是最好的。https://www.infoq.cn/article/MLMK2bx8uaNb5xJm13SWhttps://juejin.cn/post/6844903662548942855外接纹理的基本概念其实上面两篇闲鱼的文章,已经把外接纹理的概念讲解的比较清楚了,下面我们就简单的总结一下。首先,Flutter的渲染机制与Native渲染完全隔离,这样的好处是Flutter可以完全控制Flutter页面的绘制和渲染,但坏处是,Flutter在获取一些Native的高内存数据时,通过Channel来进行传递就会导致浪费和性能压力,所以Flutter提供了外接纹理,来处理这种场景。在Flutter中,系统提供了一个特殊的Widget——Texture Widget。Texture在Flutter的Widget Tree中是一个特殊的Layer,它不参与其它Layer的绘制,它的数据全部由Native提供,Native会将动态渲染数据,例如图片、视频等数据,写入到PixelBuffer,而Flutter Engine会从GPU中拿到相应的渲染数据,并渲染到对应的Texture中。Texture实战Texture方案来加载图片的过程实际上是比较长的,涉及到Flutter和Native的双端合作,所以,我们需要创建一个Flutter Plugin来完成这个功能的调用。我们创建一个Flutter Plugin,Android Studio会自动帮我们生成对应的插件代码和Example代码。整体流程Flutter和Native之间,通过外接纹理的方式来共享内存数据,它们之间相互关联的纽带,就是一个TextureID,通过这个ID,我们可以分别关联到Native侧的内存数据,也可以关联到Flutter侧的Texture Widget,所以,一切的故事,都是从TextureID开始的。Flutter加载图片的起点,从Texture Widget开始,Widget初始化的时候,会通过Channel请求Native,创建一个新的TextureID,并将这个TextureID返回给Flutter,将当前Texture Widget与这个ID进行绑定。接下来,Flutter侧将要加载的图片Url通过Channel请求Native,Native侧通过TextureID找到对应的Texture,并在Native侧通过Glide,用传递的Url进行图片加载,将图片资源写入Texture,这个时候,Flutter侧的Texture Widget就可以实时获取到渲染信息了。最后,在Flutter侧的Texture...
over 4 years ago
疫情到现在,已经两个多月了,每天看着新闻的报道,看着各大厂的公众号,每天都很充实,好像看了很多东西,但又好像什么也没看,眼瞅着人家的公众号阅读量蹭蹭蹭的上涨,1w+、10w+,再看看自己的公众号零零碎碎的阅读量,我不禁陷入了沉思——为什么我的公众号没人看!我觉得是时候来分析一下了,让我们来看看,如何打造一篇阅读量高的公众号文章标题。作为一个技术公众号,我们来想一个最基本的名字,然后再一步步进行迭代。例如,我准备写一篇文章——《Kotlin协程基础学习》平平淡淡的标题透露着作者菜菜的水平,假如我是一个自认为牛逼的开发者,我才不屑于看这种「基础」文章,仿佛拉低了我的水平,所以,我们修改下标题——《Kotlin协程-核心原理与分析》嗯,有点味道了,看上去有点「资深」的感觉了。但是,这样的标题又会让很多初学者望而却步,所以,为了能够让文章的受众更广,我又进行了迭代——《Kotlin协程-常见面试题分析》一篇文章,让你轻松应付面试,这受众一下子就打开了,看来这个标题也不错。不过,这些标题和那些大厂,以及我发的「广告」相比,还是差了点,我们来看看它们是怎么写的。《吐血推荐!Kotlin协程面试精选》《万字长文!搞定Kotlin协程方方面面》《Kotlin协程,你不得不知的真相》《再不学就废了!Kotlin协程是找工作的敲门砖》《一道Kotlin面试题引发的血案》卧槽,果然有点东西,加了几个「浮夸性」修饰词,瞬间让逼格就起来了,让人很有点击的欲望。类似的,还有——《全网最干货-解读Kotlin协程核心原理》《生动图解-Kotlin协程图文分析》《全网最硬核Kotlin协程分享》这类的文章,点击率和收藏可能非常多,但真正读的,可能没几个,不管文章干不干,写了就是干货,不管图生不生动,加了就生动。当然,有一些确实很有实力的大佬,可以写出这样的文章,但这样的文章,的确是可遇不可求,所以这类文章,通常都是两个极端,要么极好,要么极差。再加上这几年各种自媒体对「35岁」的炒作,现在的广告普遍变成了下面的风格——《搞定Kotlin协程,大厂随便进》《今年三十五,找工作还在被问Kotlin协程》《搞不懂Kotlin协程,要失业了》各种贩卖焦虑的标题,让人真的很焦虑。也许你本来不焦虑,但焦虑的人多了,你也踏上了焦虑的路。除了贩卖焦虑,还有一种贩卖「人设」的套路,通过一些名人效应,来吸引读者的点击,例如——《阿里内部疯传的Kotlin协程学习资料》《三星大牛AvLin老师带你手撕Kotlin协程》《阿里P9面试官最喜欢的Kotlin协程面试题》《看完这篇Kotlin协程分析,吊打腾讯面试官》太牛逼了吧,这么多大佬带我学习,看完这篇文章,我应该可以升P10了,吊打P9。除了这种「大牛系」人设,还有一种「女友系」人设——《手把手教妹子Kotlin协程,结果……》《睡前给妹子讲了Kotlin协程,没想到……》这类的文章,真的是——一言难尽。分析了这么多标题,看来要想提高阅读量,还是挺简单的,不就是:浮夸修饰词、震惊体大而全,全网、全公司、最硬核贩卖焦虑卖人设原理很简单,但是看完自己的分析,我决定给这篇文章起名——《再谈协程》花里胡哨的鬼话学不来,一个好的标题,的确是一篇公众号文章阅读量的基石,但我觉得,更加真诚的标题,才是技术公众号最好的口碑。我也会在公众号中取一些比较有意思的标题,就像现在的几个系列文章:「再谈协程」系列「FlutterComponent最佳实践」系列「Flutter混编之路」系列「Kotlin修炼指南」系列希望能在尽可能的吸引读者的同时,最大限度的用贴近技术的词汇来取名。向大家推荐下我的网站 https://xuyisheng.top/ 专注 Android-Kotlin-Flutter 欢迎大家访问
over 4 years ago
最后一篇文章,我们在掌握了如何读取状态值,并知道如何根据不同场景选择不同类型的Provider,以及如何对Provider进行搭配使用之后,再来了解一下它的一些其它特性,看看它们是如何帮助我们更好的进行状态管理的。Provider Modifiers所有的Provider都有一个内置的方法来为你的不同Provider添加额外的功能。它们可以为 ref 对象添加新的功能,或者稍微改变Provider的consume方式。Modifiers可以在所有Provider上使用,其语法类似于命名的构造函数。final myAutoDisposeProvider = StateProvider.autoDispose<int>((ref) => 0) final myFamilyProvider =...
over 4 years ago
前面一篇文章,我们了解了如何正确的去读取状态值,这一篇,我们来了解下不同的Provider都有哪些使用场景。这篇文章,我们将真正的深入了解,如何在不同的场景下,选择合适的种类的Provider,以及这些不同类型的Provider,都有哪些作用。不同类型的ProviderProvider有多种类型的变种,可以用于多种不同的使用场景。在所有这些Provider中,有时很难理解何时使用一种Provider类型而不是另一种。使用下面的表格,选择一个适合你想提供给Widget树的Provider。 Provider Type Provider Create Function Example Use Case Provider Returns any...
over 4 years ago
熟悉我的朋友应该都知道,我好几年前写过一个「Flutter状态管理之路」系列,那个时候介绍的是Provider,这也是官方推荐的状态管理工具,但当时没有写完,因为写着写着,觉得有很多地方不尽人意,用着很别扭,所以在写了7篇文章之后,就暂时搁置了。一晃时间过了这么久,Flutter内部依然没有一个能够碾压一切的状态管理框架,GetX可能是,但是我觉得不是,InheritedWidget系的状态管理,才应该是正统的状态管理。最近在留意Provider的后续进展时,意外发现了一个新的库——Riverpod,号称是新一代的状态管理工具,仔细一看,嘿,居然还是Provider的作者,好家伙,这是搬起石头砸自己的脚啊。就像作者所说,Riverpod就是对Provider的重写,可不是吗,字母都没变,就换了个顺序,这名字也是取的博大精深。其实Provider在使用上已经非常不错了,只不过随着Flutter的更加深入,大家对它的需求也就越来越高,特别是对Provider中因为InheritedWidget层次问题导致的异常和BuildContext的使用这些问题诟病很多,而Riverpod,正是在Provider的基础上,探索出了一条心的状态管理之路。大家可以先把官方文档看一看 https://riverpod.dev ,看完之后发现还是一脸懵逼,那就对了,Riverpod和Provider一样,有很多类型的Provider,分别用于不同的场景,所以,理清这些Provider的不同作用和使用场景,对于我们用好Riverpod是非常有帮助的。官网的文档,虽然是作者精心编写的,但它的教程,站在的是一个创作者的角度,所以很多入门的初学者看上去会有点摸不清方向,所以,这才有了这个系列的文章。我将在这个系列中,带领大家对文档进行一次精读,进行一次赏析,本文不全是对文档的翻译,而且讲解的顺序也不一样,所以,如果你想入门Riverpod进行状态管理,那么本文一定是你的最佳选择。Provider第一眼首先,我们为什么要进行状态管理,状态管理是解决申明式UI开发,关于数据状态的一个处理操作,例如Widget A依赖于同级的Widget B的数据,那么这个时候,就只能把数据状态上提到它们的父类,但是这样比较麻烦,Riverpod和Provider这样的状态管理框架,就是为了解决类似的问题而产生的。将一个state包裹在一个Provider中可以有下面一些好处。允许在多个位置轻松访问该状态。Provider可以完全替代Singletons、Service Locators、依赖注入或InheritedWidgets等模式简化了这个状态与其他状态的结合,你有没有为,如何把多个对象合并成一个而苦恼过?这种场景可以直接在Provider内部实现实现了性能优化。无论是过滤Widget的重建,还是缓存昂贵的状态计算;Provider确保只有受状态变化影响的部分才被重新计算增加了你的应用程序的可测试性。使用Provider,你不需要复杂的setUp/tearDown步骤。此外,任何Provider都可以被重写,以便在测试期间有不同的行为,这可以轻松地测试一个非常具体的行为允许与高级功能轻松集成,如logging或pull-to-refresh首先,我们通过一个简单的例子,来感受下,Riverpod是怎么进行状态管理的。Provider是Riverpod应用程序中最重要的部分。Provider是一个对象,它封装了一个state并允许监听该state。Provider有很多变体形式,但它们的工作方式都是一样的。最常见的用法是将它们声明为全局常量,例如下面这样。final myProvider = Provider((ref) { return MyValue()...
over 4 years ago
又到了Flutter稳定版发布的时候了--我们非常自豪地宣布Flutter 3! 仅仅三个月前,我们宣布Flutter支持Windows。今天,我们很高兴地宣布,除了Windows之外,Flutter现在在macOS和Linux上也是稳定的!感谢我们的Flutter贡献者的辛勤工作,我们已经合并了5248个pull requests!作为这个版本的一部分,我们有几件令人兴奋的事情要宣布,包括Flutter对macOS和Linux的支持的更新,显著的性能改进,移动和网络的更新--以及更多。此外,我们还有关于减少对旧版Windows的支持的消息,以及一个简短的breaking变化清单。所以,让我们开始谈正事吧!Ready for production on all desktop platformsLinux和macOS已经达到稳定,包括以下功能。Cascading menus and...
over 4 years ago
我们在手机、桌面和网络上进行多平台UI开发的历程达到了顶峰。我们很高兴地宣布,作为谷歌I/O主题演讲的一部分,我们今天推出了Flutter 3。Flutter 3完成了我们从以移动为中心到多平台框架的路线图,提供了对macOS和Linux桌面应用的支持,以及对Firebase集成的改进,新的生产力和性能特性,并支持Apple Silicon。The journey to Flutter 3我们创办Flutter的初衷是试图彻底改变应用开发:将网络的迭代开发模式与硬件加速图形渲染和像素级控制相结合,而这在以前是游戏的专利。自Flutter 1.0测试版以来的四年里,我们逐渐在这些基础上发展,增加了新的框架功能和新的小工具,与底层平台更深入的整合,丰富的包库和许多性能和工具的改进。随着产品的成熟,越来越多的人开始用它构建应用程序。今天,有超过50万个应用程序是用Flutter建立的。来自data.ai等研究公司的分析,以及公众的评价,表明Flutter被许多细分领域的客户所使用:从微信等社交应用到Betterment和Nubank等金融和银行应用;从SHEIN和trip.com等商务应用到Fastic和Tabcorp等生活方式应用;从My BMW等伴侣应用到巴西政府等公共机构。今天,有超过50万个应用程序使用Flutter构建。开发人员告诉我们,Flutter有助于在更多的平台上更快地构建漂亮的应用程序。在我们最新的用户研究中。91% 的开发者认为 Flutter...