Tab 键或箭头键导航进入或离开此键区,而是必须按键区导航键盘组合键。
视图默认焦点
在 Android 8.0 中,您可以指定在(重新)创建的操作组件继续运行并且用户按下键盘导航键(例如 Tab 键)之后应接收焦点的 View。要应用“设为默认焦点”设置,请在包含界面元素的布局 XML 文件中将 View 元素的 android:focusedByDefault 属性设置为 true,或者将 true 传递至应用界面逻辑中的 setFocusedByDefault()。
系统
新的 StrictMode 检测程序
Android 8.0 添加了三个新的 StrictMode 检测程序,帮助识别应用可能出现的错误:
- detectUnbufferedIo() 将检测您的应用何时读取或写入未缓冲的数据,这可能极大影响性能。
- detectContentUriWithoutPermission() 将检测您的应用在其外部启动 Activity 时何时意外忘记向其他应用授予权限。
- detectUntaggedSockets() 将检测您的应用何时使用网络流量,而不使用 setThreadStatsTag(int) 将流量标记用于调试目的。
缓存数据
Android 8.0 优化了缓存数据的导航和行为。现在,每个应用均获得一定的磁盘空间配额,用于存储 getCacheQuotaBytes(UUID) 返回的缓存数据。
当系统需要释放磁盘空间时,将开始从超过配额最多的应用中删除缓存文件。因此,如果将您的缓存数据量始终保持低于配额的水平,则在必须清除系统中的某些文件时,您的缓存文件将能坚持到最后。系统在决定删除您的应用中的哪些缓存文件时,将首先考虑删除最旧的文件(由修改时间确定)。
您还可以针对每个目录启用两种新行为,以控制系统如何释放缓存数据:
- StorageManager.setCacheBehaviorAtomic() 可用于指示某个目录及其所有内容应作为一个不可分割的整体进行删除。
- setCacheBehaviorTombstone(File, boolean) 可用于指示不应删除某个目录内的文件,而应将它们截断到 0 字节长度,使空文件保持完好。
最后,在需要为大文件分配磁盘空间时,可考虑使用新的 allocateBytes(FileDescriptor, long) API,它将自动清除属于其他应用的缓存文件(根据需要),以满足您的请求。在确定设备是否有足够的磁盘空间保存您的新数据时,请调用 getAllocatableBytes(UUID) 而不要使用 getUsableSpace(),因为前者会考虑系统要为您清除的任何缓存数据。
内容提供程序分页
我们已更新内容提供程序以支持加载大型数据集,每次加载一页。例如,一个具有大量图像的照片应用可查询要在页面中显示的数据的子集。内容提供程序返回的每个结果页面由一个 Cursor 对象表示。客户端和提供程序必须实现分页才能利用此功能。
内容刷新请求
现在,ContentProvider 和 ContentResolver 类均包含 refresh() 函数,这样,客户端可以更轻松地知道所请求的信息是否为最新信息。
您可以扩展 ContentProvider 以添加自定义的内容刷新逻辑。请务必重写 refresh() 函数,以返回 true,告知提供程序的客户端您已尝试自行刷新数据。
您的客户端应用可通过调用另一个函数(又称 refresh()),显式请求已刷新的内容。在调用此函数时,传入待刷新数据的 URI。
注:由于您可能通过网络不断请求数据,
您应仅在有明显迹象表明内容确已过时时才从客户端调用 refresh()。
执行此类内容刷新最常见的原因是响应滑动刷新手势,
该手势显式请求当前界面显示最新内容。
JobScheduler 改进
Android 8.0 引入了对 JobScheduler 的多项改进。由于您通常可以使用计划作业替代现在受限的后台服务或隐式广播接收器,这些改进可以让您的应用更轻松地符合新的后台执行限制。
JobScheduler 的更新包括:
- 您现在可以将工作队列与计划作业关联。要将一个工作项添加到作业的队列中,请调用 JobScheduler.enqueue()。当作业运行时,它可以将待定工作从队列中剥离并进行处理。这种功能可以处理之前需要启动后台服务(尤其是实现 IntentService 的服务)的许多用例。
- 您现在可以通过调用 JobInfo.Builder.setClipData() 的方式将 ClipData 与作业关联。利用此选项,您可以将 URI 权限授予与作业关联,类似于这些权限传递到 Context.startService() 的方式。您也可以将 URI 权限授予用于工作队列上的 intent。
- 计划作业现在支持多个新的约束条件:JobInfo.isRequireStorageNotLow()
如果设备的可用存储空间非常低,作业将不会运行。
JobInfo.isRequireBatteryNotLow()
如果电池电量等于或低于临界阈值,作业将不会运行;临界阈值是指设备显示 Low battery warning 系统对话框的电量。
NETWORK_TYPE_METERED
作业需要一个按流量计费的网络连接,比如大多数移动数据网络数据套餐。
自定义数据存储
Android 8.0 允许您为首选项提供自定义数据存储,如果您的应用将首选项存储在云或本地数据库中,或者如果首选项特定于某个设备,此功能会非常有用。如需了解有关实现数据存储的详细信息,请参阅自定义数据存储。
findViewById() 签名变更
现在,findViewById() 函数的全部实例均返回
- 例如,如果 someMethod(View) 和 someMethod(TextView) 均接受调用 findViewById() 的结果,这可能导致现有代码的返回类型不确定。
- 在使用 Java 8 源语言时,这需要在返回类型不受限制时(例如,assertNotNull(findViewById(...)).someViewMethod()))显式转换为 View。
- 重写非最终的 findViewById() 函数(例如,Activity.findViewById())将需要更新其返回类型。
媒体增强功能
VolumeShaper
有一个新的 VolumeShaper 类。您可以用它来执行简短的自动音量转换,例如淡入、淡出和交叉淡入淡出。
音频焦点增强功能
音频应用通过请求和舍弃音频焦点的方式在设备上共享音频输出。应用通过启动或停止播放或者闪避音量的方式处理处于聚焦状态的变更。有一个新的 AudioFocusRequest 类。对于此类,应用在处理音频焦点变化时会使用新功能:自动闪避和延迟聚焦。
媒体指标
新的 getMetrics() 函数将返回一个包含配置和性能信息的 PersistableBundle 对象,用一个包含属性和值的地图表示。为以下媒体类定义 getMetrics() 函数:
- MediaPlayer.getMetrics()
- MediaRecorder.getMetrics()
- MediaCodec.getMetrics()
- MediaExtractor.getMetrics()
为每个实例单独收集指标,并持续到实例的生命周期结束为止