Android Jetpack Compose 超快速上手指南

Compose 介绍 Jetpack Compose发布也快有一年的时间了,虽然目前仍是DEV阶段,但是距离可用已经不远了。Compose库是用响应式编程的方式对View进行构建,可以用更少更直观的代码,更强大的功能,能提高开发速度(可以参考几乎一模一样的Flutter,开发速度确实很快)。 Jetpack Compose对于没有接触过声明式UI的小伙伴可能会学习曲线有点陡峭,对于已经能熟练开发Flutter应用的小伙白来说几乎没有难度。(Compose就是参考flutter的模式开发的,代码中还可以看到Flutter的相关注释) 这篇文章不回去解释过多的原理与技巧,只要是让你能够快速上手开发项目。 Compose 如何使用 因为目前(2020年09月27日)Compose仍处于开发阶段,所以需要使用最新 Canary 版的 Android Studio 预览版。 可以选择直接创建Empty Compose Activity来创建一个全新的Compose应用,或者可以选手动修改gradle的方式来创建Compose应用 修改Gradle 在模块的build.gradle文件中新增: android { ... kotlinOptions { jvmTarget = '1.8' useIR = true } buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion compose_version kotlinCompilerVersion '1.4.0' } } dependencies中新增: implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" implementation "androidx.ui:ui-tooling:$compose_version" 目前最新的Compose版本是1.0.0-alpha03 使用Compose最低的buildTools版本要求为29 使用 @Compose 所有关于构建View的方法都必须添加@Compose的注解才可以。并且@Compose跟协程的Suspend的使用方法比较类似,被@Compose的注解的方法只能在同样被@Comopse注解的方法中才能被调用...

九月 27, 2020 · 2 分钟 · LengYue

android 11 [api 30] 适配指南

转眼之间就该适配Android 11,记得距离上次写 Android 10 适配指南才过去不久. 行为变更:所有应用 这些变化,影响所有的应用,不管你的应用的targetSdkVersion是多少,只要是运行在Android 11 上都会影响,应该格外的关注: 数据访问审核 为了让应用及其依赖项访问用户私密数据的过程更加透明,Android 11 引入了数据访问审核功能。借助此流程得出的见解,您可以更好地识别和纠正可能出现的意外数据访问。 您的应用可以注册 AppOpsManager.OnOpNotedCallback 实例,该实例可在每次发生以下任一事件时执行相应操作: 应用的代码访问私密数据。为了帮助您确定应用的哪个逻辑部分调用了事件,您可以按归因标记审核数据访问。 依赖库或 SDK 中的代码访问私密数据。 数据访问审核是在发生数据请求的线程上调用的。这意味着,如果应用中的第三方 SDK 或库调用访问私密数据的 API,您的 OnOpNotedCallback 可以调用数据访问审核检查有关该调用的信息。通常,此回调对象可以通过查看应用的当前状态(例如当前线程的堆栈轨迹)以判断调用是来自您的应用还是来自 SDK。 单次授权 在 Android 11 中,每当应用请求与位置信息、麦克风或摄像头相关的权限时,面向用户的权限对话框会包含仅限这一次选项。如果用户在对话框中选择此选项,系统会向应用授予临时的单次授权。 在申请与位置信息、麦克风或摄像头相关的权限时,系统会自动提供一个单次授权的选项,只供这一次权限获取。然后用户下次打开app的时候,系统会再次提示用户授予权限。这个影响应该不大,只要我们每次使用的时候都去判断权限,没有就去申请即可。放一张新版本权限获取样式: JobScheduler API 调用限制调试 JobScheduler任务调度器,可以在设备空闲时做一些任务处理。Android11中如果你设置为debug模式(debuggable 清单属性设置为 true),超出速率限制的JobScheduler API调用将返回 RESULT_FAILURE。这个有什么用呢?应该可以帮助我们发现一些性能问题,感兴趣的可以自己试试。 顺便提下,Jetpack组件WorkManager也是用到了JobScheduler,不熟悉的同学可以去了解下,JobScheduler是由SystemServer进程启动的一个系统服务,所以才可以有这么大的权限。 应用使用情况统计信息 为了更好地保护用户,Android 11 将每个用户的应用使用情况统计信息存储在凭据加密存储空间中。 UsageStatsManager是Android提供统计应用使用情况的服务。通过这个服务可以获取指定时间区间内应用使用统计数据、组件状态变化事件统计数据以及硬件配置信息统计数据。 比如queryAndAggregateUsageStats方法,可以获取指定时间区间内使用统计数据,以应用包名为键值进行数据合并。 但是在Android 11 设备中,系统和任何应用都无法访问该数据,除非 isUserUnlocked() 返回 true,这发生在出现以下某种情况之后: 用户在系统启动后首次解锁其设备。 用户在设备上切换到自己的帐号。 无障碍操作 在Android手机上有个预安装的屏幕阅读服务,叫做TalkBack,为视力障碍人士或者视力状态不佳的老年人提供。那我们应用为了让这个阅读器能够读懂你的自定义view操作,必须给与自定义控件定义处理程序,包括点击,长按等操作。原来版本可能对于OnTouchListener也支持无障碍触摸事件,而在Android 11中,必须专门制定点击或者长按事件才行了 class TriSwitch(context: Context) : Switch(context) { // 0, 1, or 2....

九月 15, 2020 · 4 分钟 · LengYue

Android 声明式 UI 框架 Litho 初探 —— Sections API

在最开始入门介绍中,我们曾经用SingleComponentSection完成了一个简单的列表,当时的做法是使用 for 构造出了多个子Component。其实在 Litho 中提供了一个性能更好的方式,专门处理这种数据(这种数据其实就是类似于Android 中的adapter 与其绑定的数据)。 Litho中专门处理这种模板与列表支持的组件叫做 DataDiffSection的使用 DataDiffSection。下面用DataDiffSection我们重构一下之前写的MainListViewSpec。 首先生成我们的数据: val data = arrayListOf<Int>() for (i in 0 until 32) { data.add(i) } 在MainListViewSpec中增加一个创建ListItemView组件的方法: @OnEvent(RenderEvent::class) fun onRender(c: SectionContext, @FromEvent model: Int): RenderInfo { return ComponentRenderInfo.create().component( ListItemView.create(c) .color(if (model % 2 == 0) Color.WHITE else Color.LTGRAY) .title(if (model % 2 == 0) "hello word" else model.toString()) ....

九月 9, 2020 · 1 分钟 · LengYue

Android 声明式 UI 框架 Litho 初探 —— Layout

Litho底层使用的是Yoga,Yoga是Facebook的另一个开源项目,它是一个跨iOS、Android、Windows平台在内的布局引擎,兼容Flexbox布局方式。 所以只要熟悉Flexbox布局,那么在使用Litho进行UI布局时基本毫无压力。 如果熟悉Flutter开发,那在使用Litho时,会有一些似曾相识的感觉,Litho中的 Row 与 Column 相关属性与Flutter中的 Row 与 Column 几乎无二。 本来想写一点示例代码,但是感觉没什么可写的。下面这个链接是Yoga 官网的playground。 https://yogalayout.com/playground 你可以通过它可视化的调整UI,构建你需要的layout。同时可以生成相应的Litho代码 在线可视化构建UI: 直接生成的Litho代码: 在 Flexbox 中可以通过 positionType(ABSOLUTE)属性来实现Android 中的 FrameLayout效果: @OnCreateLayout fun createLayout(c: ComponentContext): Component { return Column.create(c) .child( SolidColor.create(c) .color(Color.MAGENTA) .widthDip(100f) .heightDip(100f) ) .child( Text.create(c) .text("FrameLayout") .marginDip(YogaEdge.TOP, 30f) .positionType(YogaPositionType.ABSOLUTE) ) .build(); } 运行效果:

九月 6, 2020 · 1 分钟 · LengYue

Android声明式UI框架 Litho 初探 —— MountSpec的使用

Mount Specs Mount Specs 用来生成渲染具体View或者Drawable的组件。 Mount spec 必须使用@MountSpec注解来标注,并至少实现一个标注了@onCreateMountContent的方法。 Mount Spec相比于Layout Spec更复杂一些,它拥有自己的生命周期: @OnPrepare,准备阶段,进行一些初始化操作。 @OnMeasure,负责布局的计算。 @OnBoundsDefined,在布局计算完成后挂载视图前做一些操作。 @OnCreateMountContent,创建需要挂载的视图。 @OnMount,挂载视图,完成布局相关的设置。 @OnBind,绑定视图,完成数据和视图的绑定。 @OnUnBind,解绑视图,主要用于重置视图的数据相关的属性,防止出现复用问题。 @OnUnmount,卸载视图,主要用于重置视图的布局相关的属性,防止出现复用问题 Android 小伙伴应该对上面这几个状态比较熟悉 这里引用一张美团技术博客的图: 下面这个代码,只是一个单纯的ColorDrawable,你也可以替换成你需要实习的View 例如 ImageView: /** * 挂载操作有一个非常类似于Android的RecyclerView Adapter的API。 * 它有一个 onCreateMountContent 方法,用于在回收池为空时创建和初始化 View 和 Drawable 内容 onMount 使用当前信息对复用的内容进行更新。 * * 预分配 * 当挂载 MountSpec 组件时,其 View 或 Drawable 内容需要从回收池中初始化或重用。 * 如果池为空,那么将创建一个新实例,这可能会使UI线程过于繁忙并丢弃一个或多个帧。为了缓解这种情况,Litho 可以预先分配一些实例并放入回收池中。 * */ @MountSpec(poolSize = 0, canPreallocate = true, isPureRender = true) class MainColorViewSpec { private const val TAG = "MainColorViewSpec" // onCreateMountContent 的返回类型应该始终与 onMount 的第二个参数的类型匹配。它们必须是 View 或 Drawable 子类。参数在构建时进行校验。 // onCreateMountContent 不能接收 @Prop 或任何带有其他注解的参数。 @OnCreateMountContent fun onCreateMountContent(context: Context): ColorDrawable { Log....

九月 5, 2020 · 2 分钟 · LengYue

Android声明式UI框架 Litho 初探 ——两种数据类型

Litho中包含的的两种数据类型 Litho的两种属性分别是: 不可变属性称为Props 可变属性称为State 不可变属性Props 定义和使用props Props属性:Component中使用@Prop注解的参数集合,具有单向性和不可变性,可以在左右的方法中访问它的指。在同一个Component中我们可以定义和访问相同的prop 下面这个例子,定义了两个Prop,一个string类型text,一个int类型index,text的注解中optional = true表示它是一个可选参数。 当Component的生命周期方法被调用的时候,@Prop参数会保存component创建时从它们的父级传递过来的值(或者它们的默认值) 设置props prop参数其实在前几篇文章中都有使用过,用起来也没有什么特别的地方,这里不在赘述,制作一个简单的说明。 Component中的prop参数会在编译时候自动加入到Builder中,以上面的代码举例: PropComponent.create(c).index(10)./*text("测试文本").*/build() Prop的默认值 对于可选的Prop如果不设置值,就是java的默认值。或者你也可以使用@PropDefault注解然后添加默认值。 如果你使用Kotlin,那还需要加上@JvmFiel把该字段编辑为public才行。 @MountSpec object PropComponentSpec { @JvmField @PropDefault val prop1 = "default" @JvmField @PropDefault val prop2 = -1 资源类型 在Android开发中,我们经常会限定参数的类型。比如: fun doSomething(@ColorInt color: Int, @StringRes str: Int, @DimenRes width: Int){} 在Compontent的Prop中也有类似的操作,具体看代码: fun onMount( c: ComponentContext, textView: TextView, @Prop(optional = true,resType = ResType.STRING) text: String?...

九月 5, 2020 · 2 分钟 · LengYue

Android声明式UI框架 Litho 初探——基础使用

初衷 Litho作为一个高性能的UI引擎,学习曲线还是比较高的,但是在国内能用的资料非常少(大部分都是相互复制的”Hello Word“教程),国外除了Litho自己的文档外,也没有太多教程。这几篇教程也是我边学边写。如果有那里理解不到位的地方,欢迎指正。 Litho 是什么 Litho是一个用于在Android上构建高效用户界面(UI)的声明性框架。但不同以往的UI框架,它的底层是Yoga,它通过将不需要交互的UI转换为Drawable来渲染视图,通过Yoga来完成组件布局的异步或同步(可根据场景定制)测量和计算,实现了布局的扁平化。加速了UI渲染速度 在Litho中,使用组件(Component)来构建UI,而不是直接与传统的Android视图进行交互。组件本质上是一个函数,它接受不可变的输入(称为属性 props),并返回描述用户界面的组件层次结构。 如果有Flutter开发经验,那么Litho的开发方式有点类似 接下来的教程都将结合代码进行讲解 基础配置 gradle apply plugin: 'kotlin-kapt' dependencies 中加入 // Litho implementation 'com.facebook.litho:litho-core:0.37.1' implementation 'com.facebook.litho:litho-widget:0.37.1' kapt 'com.facebook.litho:litho-processor:0.37.1' // SoLoader implementation 'com.facebook.soloader:soloader:0.9.0' // For integration with Fresco implementation 'com.facebook.litho:litho-fresco:0.37.1' // Sections implementation 'com.facebook.litho:litho-sections-core:0.37.1' implementation 'com.facebook.litho:litho-sections-widget:0.37.1' compileOnly 'com.facebook.litho:litho-sections-annotations:0.37.1' kapt 'com.facebook.litho:litho-sections-processor:0.37.1' 初始化SoLoader.Litho依赖,SoLoader用于加载底层布局引擎Yoga SoLoader.init(this, false); 使用基础Component Component Specs Litho中的视图单元叫做Component,可以直观的翻译为组件 组件分为两种类型 : Layout Spec:将其他组件组合到特定的布局中。这相当于 Android 上的 ViewGroup 。...

九月 5, 2020 · 1 分钟 · LengYue

vSphere, ESXi 和 vCenter 的区别

update:2020年03月26日 经理了一番折腾之后,最终公司、家里都安装上PVE了,没错就是PVE。虽然最开始特别想使用ESXI。 首先说一下之前的误解,KVM的界面是非常难看的,没想到这个基于KVM的PVE其实还好。UI还不错。 再有,ESXI不知道何故在联想的电脑上装上去打不开,UEFI BOIS 都试过了,网上的几种方法试了还是不行,在家里机器上试了一会下轻松装上~~。 最后不得不说,PVE真香~内存占用方面,最先版PVE 6.1基于Debian 9 ,内存方面控制的很好!! 最近准备把家里之前的Windows + Vmware 的服务器,物理机虚拟化。考虑了ESXI、PVE、XEN。 首先感觉XEN比较老,有点落伍,PVE 核心也是 KVM。所以最后无非就是在 ESXI 和 PVE 里选 这两个都没问题的。 最后选了ESXI。不选KVM主要是界面丑。真的丑。 Vmware 用的最多的应该是虚拟机了。刚开始 Vmware vSphere、EXSi、vCenter 搞得有点蒙。所以查资料了解了一下 vSphere 和他的组件。 首先弄清楚 vSphere,EXSi 和 vCenter 的区别是很重要的。我先在VMware Workstation 中安装了 vSphere。 vSphere是一个属于数据中心产品的软件套件。vSphere就像微软 Office 套装一样拥有许多产品,比如 Office,Excel等。vSphere同样也包括很多软件组件,比如 vCenter、ESXi、vSphere client 等等。所以这些软件的合集,就叫做vSphere。vSphere不是一种你可以安装和使用的软件,它仅仅是一个软件套件的合集。 ESXi、vSphere client 和 vCenter 都是 vSphere 的部件。ESXi server是最重要的部分,ESXi是一个一类虚拟化管理器(type 1 hypervisor)。所有的虚拟机或者客户机操作系统都安装在 ESXi 服务器上,同时,你可能还需要vSphere中的其他部件– vSphere client 或者 vCenter。管理员可以通过 vSphere client 连接 ESXi 服务器来访问或者管理虚拟机。vSphere client 是用来从客户端机器连接 ESXi 执行任务的。所以,现在的问题是,vCenter是什么?我们为什么需要他?我们完全可以通过 vSphere client来克隆虚拟机,而不需要 vCenter server。...

三月 18, 2020 · 1 分钟 · LengYue