65.9K
CodeProject 正在变化。 阅读更多。
Home

Android Studio 3.0 - 影响与可能性

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.77/5 (12投票s)

2017 年 11 月 12 日

CPOL

12分钟阅读

viewsIcon

25414

Android Studio 3.0 中的一些新功能概述

引言

Android Studio 3.0 终于发布了。我等了好几个月。虽然对许多开发者来说,这“不过是下一个版本,哇,我们可以使用 lambda 表达式了”,但现在有一些非常有趣的功能可以使用了。

这些功能没有一个是全新的,其中一些您可能从未接触过,但也许本文能激励您尝试一些新东西。

本文绝不(甚至远远没有)尝试向您展示“所有新功能”,也不会提供完整的“新增内容列表”。这是一份我在使用 3.0 正式版的第一周里引起我注意的功能列表。

在本文中,我们将探讨以下主题:

  • 当前版本的 Android Studio/Gradle 中的 Bug
  • 新的编辑器功能和 Live Templates
  • 简要了解一些 Java 8 功能(网上已经有很多关于此主题的文章,我不想重复所有内容)
  • 模拟器有什么新变化
  • 更新 build.gradle 中的新内容 - 全能的 "implementation" 和 "api"

发现的 Bug

每个新版本都会有一些 Bug。其中许多 Bug 大多数用户都没有意识到,更不用说一个人能遇到了。

构建系统

我在处理我的库时,在 gradle 构建工具 3.0.0 中发现了一个 Bug,我在这里展示它,因为当您使用 .aar 库时,您会遇到这个 Bug。

该 Bug 已提交给 Google,他们已将其报告为“已修复”,使用构建工具 3.0.1。因此,在下一个 Android Studio 补丁中,我们可以期望它不再发生。

https://issuetracker.google.com/issues/68741204 Bug 的问题在于,gradle 会错误地将附加到构建的文件/文件夹报告为“已修改”并导致失败。因此,如果您遇到因修改了“layout-v16”文件而导致的构建错误,即使您的 minApi > 16,那也正是这个 Bug。修复程序正在途中。

在此之前,如果您在 Android Studio 3.0 中遇到此行为,则需要重建整个项目。我的经验表明,每次更改 XML 文件(资源、布局、主题等)时,您都需要重建所有内容。仅 Java 更改不会导致此 Bug 出现。

更新 2017-11-26: Android Studio 3.0.1 补丁已发布。您可以将项目 build.gradle 更新为

classpath 'com.android.tools.build:gradle:3.0.1'

现在。Bug 修复已发布,我可以确认,所述行为确实不再发生。

查找窗口

另一个 Bug 与查找窗口有关,有时删除的行会在搜索结果中显示错误的“INVALID”标记。该 Bug 已在此处提交,仍在调查/重现阶段:https://issuetracker.google.com/issues/68806074。您可以在此 Bug 中找到一个简短的屏幕录像视频,以了解发生了什么。如果您也遇到此行为,请给该问题加星标。

构建工具版本设置为 26

另一位用户报告并我赞同的一个 Bug 是,即使您已将所有项目都转换为 27,目前也需要安装构建工具 26。当您创建项目时会出现此 Bug。Gradle 会假定使用构建工具 26,尽管新定义说明“您不再需要指定构建工具版本。Gradle 将默认使用已安装的最新版本。”

虽然默认设置是正确的,但在撰写本文时,它适用于新项目。所以请记住,暂时不要卸载 v26 - https://issuetracker.google.com/issues/68301941

编辑器功能和 Live Templates

您是否知道并使用 C# 的 #region?这是一个很好的代码区域折叠功能,可以帮助您更好地管理大型代码文件,并且对于在类中构建“逻辑块”也很有帮助。

Android Studio (IntelliJ) 也有类似的功能。它在 3.0 中并不是新功能,但 Android Studio 的“结构”代码视图现在支持它,这对我是个很大的补充。

Visual Studio 中的语法是

#region My foldable section
public void SomeMethod()
{
//...
}
#endregion

在 Android Studio 中,它看起来是这样的

// <editor-fold desc="Properties">
public void someMethod { 
} 
// </editor-fold>

我们可以清楚地看到 Visual Studio 的方式要方便得多。“#region”输入起来非常快,并且不会真正中断您的编码流程,而输入带有 desc 属性的 XML 标签并不那么容易。

我认为这是该功能很少被 Android 开发者使用的主要原因之一。为了解决这个问题,我将与您一起创建一个简短的 Live Template,以便您可以在 Android Studio 中像在 Visual Studio 中一样轻松地使用“regions”。

在两个 IDE 中,效果都是一样的:您会在代码视图的左侧边框上看到一个小的 (+) 图标,允许您折叠/展开该区域。这样您就可以轻松地隐藏部分代码。

Android Studio 3 中的新功能是,“结构”窗口现在完全支持这些编辑器折叠区域,这大大提高了结构视图的可读性和可用性!

我个人非常喜欢使用区域/折叠,在我的类中,没有一行代码,没有一个方法不与某个区域相关联/放在某个区域中。这对于我所有的 C# 程序以及我的 Android 应用都适用。

如果您允许,我想建议您给“结构”视图一个机会。打开它,将其重新排列到 Android Studio 的右侧,这样在编码时,您就可以在左侧看到项目视图,在右侧看到结构视图。它将提高您的导航速度。您可以在“窗口”菜单(其中第一个菜单项)中将窗口布局保存为“默认”,这样您就不必在每次会话中都重新排列窗口了。

看看这张带有编辑器折叠的代码视图和对应的结构视图的截图。我只需要用眼睛快速浏览一小部分区域名称,就能找到方法所在的位置,而不是阅读几十个方法名并滚动浏览几乎无穷无尽的列表。

创建 Live Template

如果您以前从未创建过 Live Template:Live Template 相当于 Visual Studio 中的“代码片段”。在我看来,Android Studio 有迄今为止更好的创建这些模板的方法。我个人不太喜欢 Visual Studio 的代码片段语法,而且 VS 对编辑/创建新代码片段的支持……几乎不存在。

要在 Android Studio 中创建新的 Live Template,请按 Alt+Ctrl+S 或打开 文件 --> 设置。现在您可以导航到“Live Templates”部分,或者直接在窗口顶部的搜索框中键入“live”。然后您会看到这个

提示:为 Live Templates 创建自己的模板组,这样您就可以将所有自定义模板集中在一个地方。为此,请单击右侧边框上的绿色 + 号,然后创建一个模板组,就像我在屏幕截图中所示的“_Mike_”部分那样。

有了您的组,请再次单击绿色 + 号并创建一个新的“Live Template”。之后您会看到这个

  1. “缩写”是您之后在代码编辑器中输入以启动模板的内容。选择一个简短的、与模板相关的、并且您能记住的。在我的例子中,它是“ef”,表示“editor fold”。您可以通过输入 ef + Tab 键来启动此模板。
  2. 这只是一个简短的信息消息,将在 IntelliSense 中显示。在演示模板时,您将在下面的屏幕截图中看到。
  3. 这最终是您的模板代码。这里的语法非常简单:所见即所得。输入您想在代码窗口中看到的内容!用$美元符号$括起来的每个术语都被视为一个变量,在按下编辑变量按钮时可以进行编辑(并接收默认值)。启动模板时,Android Studio 会停在第一个变量处,并允许您输入一个值。使用 Tab 键逐个步进多个变量。

    模板文本文本框中输入此内容

    // <editor-fold desc="$section$">
    // </editor-fold>
  4. 这是最重要的一部分。您必须定义该模板可以启动的范围。对于这个特定的模板,它是“声明”,因为我们希望它在 Java 允许我们声明任何内容时可用。一个成员、一个方法……这是我们想要区域来分组代码元素的地方。

应用您的更改并关闭设置窗口。

使用模板

现在打开一个代码文件,开始输入“ef”,看看 IntelliSense 为您提供了什么

很棒,不是吗?只需 2 个字符,您就输入了这个复杂的 XML 标签(复杂指的是“尝试手动输入”)。

正如您在上面的屏幕截图之一中看到的,我创建了许多这样的模板,它们真的可以加速您的工作!

Live Template 并不是什么新鲜事物,编辑器折叠也不是。但随着新的结构视图现在显示这些折叠区域,它值得一提。

Java 8

Android Studio 现在支持 Java 8 功能。好吧,Android Studio 2.3 已经支持了,如果您启用了 Jack&Jil 工具链。这个工具链已被弃用,并且有一个重大缺陷:库项目无法用 Jack 编译。这使得我们开发者只能“再坚持一段时间使用 Java 7”或使用 RetroLambda 等第三方工具。但我们没有“真正”的方式来使用所有这些炫酷的东西。

有了 Studio 3,等待结束了。Java 8 现在已启用,Jack 已移除。您可以轻松找到大量关于 Android 中 Java 8 的文章。一个好的概述可以在这里找到:https://developer.android.com.cn/studio/write/java8-support.html

最大的影响

Java 8 中有很多好东西,但我认为最明显的影响是函数引用。

那些日子一去不复返了

view.setOnClickListener(new View.OnClickistener() {
    @Override
    public void onClick(View v) {
        // doSomething
    }
});

这是我一直不太喜欢的东西。我一直只想调用一个方法。Java 没有像 C# 那样的事件语法,而且我不想说“C# 在这里更好”。我真的很喜欢这种回调方法。但它的语法……真是太糟糕了。另一方面,对接口执行“new”操作是一件非常酷的事情!所以这枚硬币有两面,一如既往。

现在,有了 lambda,上面的代码可以更改为

view.setOnClickListener( (v) -> {
    // doSomething
});

这样更短。但有了函数引用,我们终于可以达到我想要的目标了

view.setOnClickListener(this::onClick);

private void onClick(View view) {
    // doSomething
}

那么这里有什么区别呢?

首先是语法。双冒号让我想起了 C++(没什么坏处,别误会,我只是提一下)。但我们从中获得了一个真正的优势

如果我们不将 onClick 方法设为 private,而是设为 public,那么继承者就可以简单地 @Override 该点击监听器方法!以前无法覆盖内联声明的 new View.OnClickListener(...)。但现在我们可以了!

我认为,这将是影响最明显的地方。如果您决定修改您的库并更新您的源代码以利用这些新功能(就像我一样),您应该会得到一个更干净、更易读、更易于理解的代码。

模拟器

Android 模拟器中包含了一个非常非常棒的新功能。Play 商店访问!是的,您没看错。AVD 现在开箱即用,完全可以访问 Play 商店。只需使用“Play 商店”镜像创建您的模拟器,而不是使用“Google APIs”镜像(SDK 管理器和创建新 AVD 时会提供新类型的镜像)。

启动模拟器后,您就可以像连接物理设备一样连接您的 Google 帐户!我使用了我的开发者 Google 帐户,一切正常。Gmail、日历、所有云服务都可以在 AVD 中使用。当然,还有所有 Play 商店应用。 :)

是的,甚至游戏也是。试试吧 - 很棒的新功能!

build.gradle 中的新增内容

(更新 2017-11-15)

还有一项变化应该被提及:compile(...) 命令在 build.gradle 中现在已被弃用。您会收到一个警告,说“compile 已弃用。请改用 implementation。”

这里涉及一项重要功能:compile 已拆分为两个可能的命令:implementationapi

理解这两个命令之间的区别对于处理库非常重要。简而言之,我们可以说,“它们或多或少地描述了您引用的可见性范围”。

如果您在依赖项中使用 api 而不是以前的compile,那么一切都会像使用 compile 时一样工作,但您使用 api 引用的所有库也对您当前库的用户可见。这与compile时的情况相同。

如果您使用 implementation,则引用对您的库是私有的,外部用户无法看到您的引用。

一张图胜过千言万语

那么这意味着什么?

  • 在第一张图中,库 A 和 D 使用“api”关键字引用 B 和 E,B 也使用 C。其效果是,您的应用程序可以在不引用它们的情况下使用 B、C、E。
  • 在第二张图中,A 和 D 使用“implementation”。它们当然可以使用它们的依赖项,但您的应用程序不能。应用程序只能直接访问 A、D、F。
     
  • 当您不希望您的子依赖项能够从当前项目外部被看到和使用时,您应该使用 implementation
    • 示例:您的库 B 是您的私有工具箱库,包含使您的生活更轻松的函数,但您不想“任何人”都使用您的库。因此,您的库 A 应该将对库 B 的依赖项设置为 implementation,从而将库 B 对应用程序隐藏起来。只有库 A 可以使用它。
    • 但是,如果您计划公开“公共 API”,即打算从当前项目外部访问的内容,则应将依赖项设置为 api
    • 所以最简单的经验法则就是思考这些词的含义……API 是编程接口,是可以交互的东西。如果您想要那样,请使用 api,否则请使用 implementation

构建时间

apiimplementation 会影响您系统的构建时间。如果您为子项目(B、C)使用 implementation,并且您在其中一个项目中进行了更改,您只需要重新编译 A,而应用程序可以照常使用 A,因为它不关心子项目。

另一方面,使用api时,应用程序也需要重新编译 B 和 C,因为它可以看到所有这些引用并需要更新它们。

那么这就是快速概述。我希望我能提供一两件值得思考的新事物,也许您在这里找到了您以前从未用过的一些东西!

历史

  • 2017-11-12 - 首次发布
  • 2017-11-12 - 更新:添加了模拟器部分
  • 2017-11-14 - 格式更改并添加了一个 Bug 的解决方法
  • 2017-11-26 - 更新了第一个 Bug 描述。它现在已修复。
© . All rights reserved.