概述

谷歌发布Android Studio3.0正式版已经有一段时间了,最近抽空升级了一下,也踩了一些坑.特地记录一下.作为开发者第一时间体验谷歌带来的新特性是很有必要的.当然为了项目稳定性,也要根据实际情况决定是否升级相关插件

升级

从已有的IDE升级,无非就是File->Settings->Appearance&Behavior->Updates,这里可以选择升级渠道:Canary(金丝雀)Dev(开发版)Beta(Beta版)Stable(稳定版),以及是否使用安全链接.或者Help->Check for Updates,会直接推送当前最新的稳定版.正式版貌似在本地调试方面不再支持32位Windows系统

Tips:AS除了IDE本身,还有SDK,配置文件,依赖库,默认在Win平台上都是存放在C盘,建议只把SDK文件夹单另移动到其它的硬盘,可以在AS中选择,其它的保持默认,给C盘留出足够空间.之前有照网上的更改config文件,自定义配置文件和依赖库存放的目录,但在升级的时候出现了很多问题,特别是在大版本升级的时候会出现找不到某些文件的情况

升级步骤

升级安装完毕后还需要我们做一些配置:

  • 导入IDE配置,这里我直接选择的第一项,导入之前就有的配置,包括了字体和代码格式等,有说不导入的,但没有说明原因
  • android studio 版本选哪个 android studio哪个版本好_Android

  • 打开项目后会收到更新gradle插件和gradle的提示:
  • android studio 版本选哪个 android studio哪个版本好_android studio_02

如果选择忽略,那么当前项目不会受到影响,无需更改代码,当然你也无法使用到谷歌的新特性.所以建议升级gradle插件到3.0.0,升级gradle到4.1。(两者的区别可见)。因为wall的原因,AS下载gradle的速度会非常慢,要么自行翻墙,要么用迅雷打开链接,亲测速度很快。下载好的zip包放入C:/users/{user name}/.gradle/wrapper/dists/gradle-4.1-all路径下一串乱码的文件夹下,再次启动AS时会自动解压该zip包。

  • 报错
  • android studio 版本选哪个 android studio哪个版本好_ide_03

  • 因为每次gradle的更新往往也伴随着构建工具的更新,不多说,更新就好了
  • buildToosVersion
  • android studio 版本选哪个 android studio哪个版本好_android studio_04

  • 报错信息写的很清楚,移除所在build.gradle中的buildToolsVersion(当前使用的版本是25.0.0),因为每个gradle插件版本都有对应的默认版本的build tools。3.0.0对应的就是26.0.2.但是为了更清晰并且可配置,我们还是手动将其改为需要的版本而不是移除
  • Google’s Maven repository

    报错的原因是新版AS默认使用Google’s Maven Repository用于下载依赖Android Support Library,所以,需要在工程根目录下的 build.gradle 文件中的repositories下添加google()一行代码:
repositories {
      google()
      jcenter()
  }
  • AAPT2编译报错
  • android studio 版本选哪个 android studio哪个版本好_android_05

  • 关闭AAPT2编译,在gradle.properties中加入:android.enableAapt2=false
  • 注解处理器报错
  • android studio 版本选哪个 android studio哪个版本好_谷歌_06

  • 这个项目使用的Butterknife还是比较老的7.0.1版本,只有一个库,将功能代码和注解代码都写在了一起.但是新版的gradle插件会检测代码,如果要编译的代码中还有处理注解的部分,则需要被显式的说明.我们将其更新到最新版的8.4.版本.Butterknife从8.0版本后就将库拆分为编译时和运行时的.基本上所有的注解型第三方库都可以使用新的依赖方式:

在module所在的build.gradle中用annotationProcessor代替apt引用编译类库

//旧
	dependencies {
  		compile 'com.jakewharton:butterknife:8.4.0'
  		annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
	}



//新
	dependencies {
  		compile 'com.jakewharton:butterknife:8.4.0'
  		annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
	}

*在module所在的build.gradle中移除 apply plugin: 'com.neenbedankt.android-apt'.在根目录所在的build.gradle中移除classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'.因为gradle 2.2之后官方插件中已经提供了annotationProcessor的功能来完全代替 android-apt.不移除会报错,并且android-apt的作者也在官网声明推荐使用官方插件

新特性

到这里一些常见的问题基本就修复了,现在就来体验一下Android Studio及gradle相关更新的这次改动带来的一些新特性:

1.颜值的变化

AS3.0的基础IDE从IntelliJ 2016.2升级到2017.1.2,这些特性如果你使用过Idea的新版的话已经可以发现。相对应的,界面风格相比之前更Idea化了

  • 旧版的依赖库指示:以项目的名称排列
  • android studio 版本选哪个 android studio哪个版本好_android studio_07

  • 新版的依赖库指示:以库的全称,按首字母排序(目前没发现更方便)
  • android studio 版本选哪个 android studio哪个版本好_ide_08

2.支持Kotlin

支持将Java代码直接转化为Kotlin语法的代码。定位到要转换的Java代码,顶部选择Code -> Convert Java File to Kotlin File,可能会提示是否要修改项目中其它部分的代码,因为转换后带来的变化,根据需要选择。转换完成后文件的后缀名由.java变为.kt

3.Android Profiler

全新的性能分析器,可以从View->Tool Windows,找到Android Profiler。也可以直接从工具栏进入。你可以将其看作是在调试应用,和Debug类似,选择已连接的设备,开始分析本地工程。其中包含了CPU、Memory、Network。下面是官方的介绍图:

①选择的设备和;②选择要分析的应用程序的包名;③时间轴缩放控制及重置;④有点类似于暂停,动作暂停但时间轴不停止和;⑤一个事件时间线展示出活动状态,点状按钮指示用户的手势,以及屏幕旋转事件。文字展示页面的跳转和某些生命周期的标记

CPU和Memory不多说,可用来指示页面频繁变化或请求时性能的消耗情况,重点是Network:以前的功能相对单一,就是可以指示某个阶段请求发送和接收数据的大小,新版则加入了抓包功能。默认该功能是关闭的,需要我们进入Run->Edit Configurations自行开启:

android studio 版本选哪个 android studio哪个版本好_android_09

开启后重新启动Profiles,可以在调试的应用上进行一次网络请求,定位到该三角区域后就可以获取抓包的详细信息。包括Response,Headers和Call Stack。但是我在测试的过程中发现请求列表也包含了调试过程中已经发送的请求,但是不会给返回信息,切换的时候也不是很灵敏,并且这种抓包方式需要手动界定范围,目前功能也还比较简陋。

以前混在Android Monitor中的控制台,现在已经独立出来,默认界面就有Logcat一栏,调试应用时输出的日志都可以在这里看到

4.Device File Explorer

AS在之前的版本中操作连接的设备进行调试,是通过Tools->Android->Android Device Monitor启动的,其中包括了DDMS(Dalvik Debug Monitor Servic)和Hierarchy View(层级视图)两大块.并且是作为一个新窗口重新打开的,速度有点慢

android studio 版本选哪个 android studio哪个版本好_android studio_10

我这里连接的设备是小米,没有获取Root权限,无法用chmod命令更改读写权限,因此也就不能看到data/data目录下的文件,而我们想要操作的文件一般都在这个文件夹下.

在新版中,通过Device Fie Explorer很方便,View->Tool Windows->Device File Explorer就可以查看该应用所生成的文件。还可以进行新建和删除文件(包括文件夹),上传(导入)和另存为(导出)的操作,非常方便。貌似release版本的应用是无法操作的,也就是你在不Root的情况下也是无法通过Explorer查看安装在该设备上其它公司app的文件的

android studio 版本选哪个 android studio哪个版本好_谷歌_11


需要注意的是,原先的Android Device Monitor所有功能仍然保留

5.APK Debugger

需要注意的是,关联Java Source Code,照样需要关联源码,也就是原工程。不过对于一些知名的apk,你还是可以通过这个工具看到AS从apk解压后的.dex文件反编译出来的.smali文件,以及AndroidManifest.xml一探究竟。

6.依赖方式的变化

2.X版本中新增库的依赖方式

android studio 版本选哪个 android studio哪个版本好_谷歌_12

3.0新版本中的依赖方式

android studio 版本选哪个 android studio哪个版本好_ide_13

可以理解的对应关系如下:

2.X版本

3.0版本

Compile

API、Implementation

Provided

Compile only

APK

Runtime only

Test compile

Unit Test implementation、Test implementation

Debug compile

Debug implementation

Release compile

Release implementation

在实际应用中,写到module里面的build.gradle中的写法当然和这里的选项还不一样,类型更多。重点关注的是Compile的变化。在新版中,不再推荐使用compile引入依赖库,被api和implementation替代。api跟compile相同,只是名称的推荐写法。而新版本中谷歌推荐默认用implementaion依赖library.下图可以说明两者的区别:

android studio 版本选哪个 android studio哪个版本好_谷歌_14


android studio 版本选哪个 android studio哪个版本好_ide_15

简单的说,implementation避免了所在的模块依赖的项目的对外暴露。如图,你可以自建一个Project,然后在Project之下新建一个moduleB(注意是library类型的,因为gradle定义库是可以被依赖的,但是application类型的是主应用,是无法被另一个module引用的),让ModuleA依赖ModuleB。如果你在ModuleB中以api 'com.github.bumptech.glide:glide:3.7.0'引用Glide,那么你在ModuleA中也可以引用Glide。但如果在ModuleB中以
implementation 'com.github.bumptech.glide:glide:3.7.0'引用Glide,那么在ModuleA中就无法引用Glide了。

这样带来的好处是明显的,gralde编译时不再频繁遍历所有嵌套的依赖是否更新,可以提高编译速度。也避免了在工程中可以调用本来你没有引用的API(你所依赖的库引用了),引入什么用什么。
需要注意的是,依赖关系是非传递性的,决定的是ModuleB的依赖方式,你更改ModuleA的依赖方式并不会影响当前工程,而只会影响依赖你的上一层Module对你内部依赖的引用。谷歌默认新建Module时引入的基础类库方式都是implementation,只建议在出现问题时才用api代替。

7.gradle打包配置的变化

因为升级后相应的gradle插件进行了升级,可能Gradle官方对Groovy的语法做了相应的修改,原先项目中的打包配置报错,outputFile为只读属性:

android{
	...
	applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def apkPath = projectDir.parent
            def releaseName = 'yck_b2b_release ' + variant.getVersionName() + '.apk'
            output.outputFile = new File(apkPath, releaseName)

        }

    }
	...

已知的解决方案都是用新的outputFileName属性替代:

android{
	...
	applicationVariants.all { variant ->
        variant.outputs.all { output ->
                def releaseName = 'yck_b2b_release ' + variant.getVersionName() + '.apk'
                outputFileName = releaseName
            }
        }

    }
	...

但这样做无法更改发布release包的生成路径,比如测试用Jenkins打包。目前没有找到新的语法中对于更改文件路径的做法,替代方案是当打包结束后,复制一份到自定义路径。复制的动作一定要在最后完成,否则相应路径下找不到APK。

android{
	...
	def outputApk
    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            if (variant.buildType.name != "debug") {
                def releaseName = 'yck_b2b_release ' + variant.getVersionName() + '.apk'
                outputFileName = releaseName
                outputApk = outputFile.absolutePath
                copyApk(outputApk)
            }
        }

    }

def copyApk(originalFile) {
    assembleRelease.doLast {
        println "最后要完成的任务"
        def targetFile = projectDir.parent
        copy {
            from originalFile
            into targetFile
        }
    }

}
...

结语