你可能不知道的Android Studio/IDEA使用技巧

工欲善其事,必先利其器

俗话说,“工欲善其事,必先利其器”,对致力于让计算机解决人类问题的程序员来说,更应该如此(打字慢还找什么借口……)

最开始以为程序员对使用技巧都比较关注,不过从自己和身边同事的交流来看,很多我常用的技巧尤其是快捷键,确实不少人都不太了解,于是就有了这篇文章。

本文基于Android Studio Mac版

Android Studio基于IntelliJ IDEA Community Edition(社区版),主要是在其基础上增加了Android插件。因此Android Studio中很多功能和IDEA是相同的。

IDEA Android插件源码
https://github.com/JetBrains/android

设置

左上角菜单 Android Studio - Preferences,打开设置对话框。可以直接搜索设置项。

设置的导入/导出

File - Import Settings / Export Settings

应用场景举例:团队共享Lint检查配置、代码格式化风格

在菜单Help - Search中,输入任意一个不了解的功能名称,例如Reformat Code,可以看到这个功能在哪打开,并打开这个功能。所以在后面的文章里,每个功能我都会给出对应的英文名,不知道怎么打开的,直接这么搜索就能找到了。

KeyMap

对于快捷键用的少,还没有养成很强使用习惯的人,可以考虑使用Eclipse MacOS风格。

本文在括号中注明的是我自己用的快捷键,大部分基于Eclipse MacOS风格,做过一些修改。

编辑

列举几个编辑器通用的功能

  • 块操作:按住Alt,上下拖动鼠标选中,可以编辑内容相似的多行。

  • 缩进:选中多行,按Tab和Shift+Tab,可以批量缩进。

  • 大部分软件中,缩放通常通过这几种方法实现:

  1. Ctrl+鼠标滚轮;
  2. 触控板双指捏合;
  3. Cmd+/-缩放
    1. 在Android Studio低版本中可用触控板双指捏合,2.3版本缩放功能关了
    2. 绝大多数浏览器可以用Cmd+/-缩放字体大小

自动补全

图中这样的情况:

  1. 如果直接按回车键,被选项会插入到光标处,还需要手动删掉光标后面的内容;
  2. 如果按Tab键,则备选项会直接替换当前的layout属性。

Scope

Scope是IDEA中的一个通用概念,表示代码范围,可以是工程最终产出的代码(Production Files),也可以包括测试代码,可以包含Library,可以指定为某些文件、目录、包,也可以自己定义。

在Find等功能中都可以使用Scope。

很有用但往往不为人知的一个Scope是Project And Libraries,除了工程文件,还包括已经同步成功的AAR中的代码。

查找与跳转

  1. Main Menu - Edit - Find,所有搜索相关功能(包括当前设置的快捷键)

  2. Main Menu - View,所有查看相关功能

  3. Main Menu - Navigate,所有导航相关功能

导航/跳转

  1. Go To Definition 选中变量、方法、类等,跳转到定义(经典的F3

  2. Navagate Back/Forward。往前、往后跳转。(Cmd+[/Cmd+])

  3. 点击父类/子类class和方法声明行左侧的上下箭头,可以跳转到父类/子类中的实现。

  1. Bookmarks

    • 在代码任意行,选择Navigate - Bookmarks - Toggle Bookmark或定义的快捷键,可以添加、删除书签

    • 选择Navigate - Bookmarks - Show Bookmarks或定义的快捷键,可以看到所有书签

    • 应用场景:适合在多个文件的某几个地方反复切换的情况。

查看

  1. Recent Files 查看最近使用的文件(Cmd+E

  2. Quick Documentation 选中变量、方法、类等,查看JavaDoc注释(F2

  • 按一下快捷键,悬浮窗查看注释
  • 继续按快捷键,可以在悬浮窗、独立小窗口、大窗口之间循环切换
  1. Type Hierarchy 选中类的声明,查看class继承关系(F4

搜索

  1. Find Usage 查看被调用情况(Cmd+Shift+G
  • 默认搜索范围(Scope)是Project Files。可点击Find窗口的设置按钮,搜索范围指定为Project Files and Libraries(没有AAR包时没有这个选项),则会包含AAR包中的调用。可参考后文中对Scope的说明。

  1. Search Everywhere 查找文件、设置等(Shift Shift

  2. 当前文件中Find、Replace字符串(Cmd+F、修改为Cmd+R

  3. 所有文件中Find、Replace字符串(Cmd+H

  4. 指定文件夹中Find、Replace字符串:右击,搜索

Project Window

点击Project视图上的设置按钮(齿轮图标),菜单中可以勾选:

  1. Flatten Packages:所有的包都在同一级扁平显示,而不是树形折叠/展开形式,例如

    1. com.demo.main
    2. com.demo.main.ui
  2. Compact Empty Middle Packages:当一个package里只有一个子package,会扁平化显示在一行,而不是折叠展开的子目录形式,例如com.demo.main

  3. com

  4. demo

  5. main

  6. com.demo.main

  7. Show Members:在Project窗口,class文件还能继续展开,查看具体的成员变量、方法。

  8. Autoscroll to Source:选择导航窗口中的文件、方法,会自动定位到源码对应位置。对于大工程容易卡顿,可以关掉。

  9. Autoscroll from Source:查看源码,会自动定位到导航窗口中的文件、方法。对于大工程容易卡顿,可以关掉。

Autoscroll from Source关闭时,点击Project视图上的定位按钮(圆圈图标),可以从当前查看的源码定位到导航栏中的文件。

Code Style

Java变量前缀(prefix)的设置

  • Code Style - Java - Code Generation - Naming - Name Prefix

  • Field设置为m,Static Field设置为s

  • 设置完成后,自动补全时会自动处理变量前缀

Reformat Code

  • Main Menu - Code:代码格式化、补全、查看相关

  • 代码格式化(Ctrl+Shift+F)

  • 格式化完成时会展示一个小气泡,点击Show reformat dialog,可勾选:

    • Optimize imports,自动优化imports
    • Rearrange Code,按照一定规则,自动调整成员变量、方法、内部类的先后顺序
  • Preferences - Editor - General - Auto Import - Optimize imports on the fly:编辑代码时自动优化import

Inspections、Analyze

Inspections是IDEA中用于代码静态检查的组件,包括语法检查、拼写检查等,IDEA的Android插件实现了Lint检查,也是基于Inspections的。

  1. Preference - Editor - Inspections:代码检查

  2. 配置分为Default和Project Default,作用范围分别是全局和当前工程

  3. Lint检查到代码问题会提示警告或错误

  4. Main Menu - Analyze - Inspect Code:在弹窗中选择Scope(范围),Inspection Profile(要检查的规则),可以对整个项目或指定Scope进行检查

  5. Main Menu - Analyze - Code Cleanup:在弹窗中选择Scope(范围),Inspection Profile(要检查的规则),可以对整个项目或指定Scope进行格式化、Lint问题自动修复、无用变量代码等自动优化

  6. Main Menu - Analyze - Analyze Dependencies:可以分析指定Scope中代码所有的依赖项。

Code Generation

  • Prefrence - Editor - General - Postfix Completion:一些常用快捷输入,例如fori可直接输入循环for (int i = 0; i < foo; i++) {}

  • Prefrence - Editor - Live Templates:快捷输入,例如psvm输入public static void main(String[] args){},也可以自己定义

  • Main Menu - Code - Generate

  • 继承方法:直接输入父类方法名前缀,自动补全默认的继承方法

  • 输入set、get,自动创建setter、getter

Intentions(Quick Fixes):没有做不到的,只有想不到的

Intentions意为“意图”,是IDEA中用于代码高级补全、自动修复的机制。在菜单Preference - Editor - Intentions中,可以查看和开关各种Intentions。

在任意代码位置,打开Show Intention Actions 自动补全(Cmd+1),即可选择Intentions Actions操作。

  1. 各种代码补全

    • Parcelable补全实现
    • 创建构造函数
    • 变量赋值移动到声明
  2. 语法级别问题的自动优化/修复

    • 添加强制转换
    • 添加变量声明
    • 添加try-catch或方法增加throw…
    • 创建调用super的构造函数
    • 逻辑表达式化简、无用逻辑删除(例如if(true){ ... }
  3. Android Lint问题自动修复(由IDEA中的Android插件实现)

  • 解决Lint问题(例如Layout中的字符串提取到Strings中)
    • 添加SupressLint
    • 可以关闭当前工程中的这类问题的检查,如图

举例:快速创建字符串资源

  1. Layout文件中,text属性直接用了文本,没有引用String资源,会有Lint警告
  2. 光标点选文本,按Intentions的快捷键,选择Extract string resource
  3. 弹出窗口输入资源的id,确认即可

举例:快速创建XML资源文件

写Layout时,需要给ImageView写一个ShapeDrawable资源文件

  1. 常规方法:
  • 从左侧找到Drawable目录
  • 右击,创建Drawable资源文件
  • 切换回Layout,引用创建的资源文件
  1. Intentions实现:直接在src属性中填上drawable文件的名字,会标红提示没有这个资源文件,按Intentions快捷键,选择Create Drawable Resource File,弹窗点击确认即可。

Refactor

Rename(Shift+F6)

  • 按Shift+F6重命名:变量、类名、文件名、文件夹、包名、资源文件等

  • 重命名变量,会弹窗提示是否同步重命名getter、setter

  • 默认注释中的名字也会被同步改变;资源文件中的引用也会改变

  • 连续按两次Shift+F6可以打开重命名窗口,勾选/取消勾选findInComment,避免修改到错误的地方

要注意的坑

  1. 对于名字比较短的情况,特别是资源文件、id等,很容易和注释中的东西重名,重构过程中应该先看下引用,防止误修改到错误的内容。一般会自动打开Refactoring Preview窗口预览要改的所有位置,右击选择Exclude/Include可以包含、取消要改的地方。

  2. 资源文件中的.9.png图片,重命名时容易丢失.9扩展名,需要特别注意

Move (Cmd+Alt+V)

  • 移动package(多个module中相同的包会被同步移动)
  • 移动文件夹(不会处理其他module)
  • 移动文件、Class
  • 移动静态方法、常量

举例:XXConstants的抽取

通过Move,可以快速把代码中散落在各个文件中的SharedPreference常量,统一移动到名为SPConstants的interface中。

Change Signature (Cmd+Alt+S)

  • 改变方法签名
  • 方法名可改变
  • 参数可以调整顺序、改变名字、类型等
  • 新增的参数,可以设置默认值,会尽可能自动匹配并填充

Extract与Inline

这里快捷键做过较多改动,目前我的设置是Inline统一用快捷键Cmd+Alt+I,Extract快捷键见括号。

  • Extract/Inline Constants (Cmd+Alt+C)

  • Extract/Inline Field (Cmd+Alt+F)

  • Extract/Inline Local Variable (Cmd+Alt+L)

  • Extract/Inline Method (Cmd+Alt+M)

  • 勾选static可抽取成static方法

  • 可修改Parameter,同Change Signature

  • Extract/Inline Class (右键菜单-Refactor)

  • Extract/Inline Layout (右键菜单-Refactor)

  • Extract/Inline Style (右键菜单-Refactor)

注意:

  • Extract Method如果选中的代码块中产生了超过一个后面会用到的变量,就不能直接Extract,默认会提示可以建一个Object实现

  • Inline Method,如果Method中有分支return,就不能直接Inline,需要手动处理。

举例:快速抽取工具类

  1. 想抽取一个LogUtil方法,用于输出Log。

    1. void func() {
    2. Log.d("tag", System.currentTimeMillis() + "");
    3. }
  2. 选中System.currentTimeMillis() + "",Extrac Variable。

  3. void func() {

  4. String msg = System.currentTimeMillis() + "";

  5. Log.d("tag", msg);

  6. }

  7. 选中代码块Log.d("tag", msg);,Extrac Method。

  8. 输入方法名,同时勾选static。

  9. Refactor-Move,移动到工具类。如果输入的工具类没建,还会提示并自动创建。

  10. public class LogUtils {

  11. public static void log(String msg) {

  12. Log.d("tag", msg);

  13. }

  14. }

  15. void func() {

  16. String msg = System.currentTimeMillis() + "";

  17. LogUtils.log(msg);

  18. }

举例:内联接口和父类

写了一个抽象类class Cls implements MyInterface,实现了接口,现在想把接口去掉,抽象方法直接定义在抽象类中

  1. 光标选中MyInterface
  2. Inline
  3. 选择As is
  4. 注:继承类的情况也可以这么用,不过可能会有一些同名变量等冲突,需要手动再处理下。

举例:匿名内部类移到成员变量中

  1. 要将直接实例化的匿名类移到成员变量中,原代码如下。

    1. void f() {
    2. setRunnable(new Runnable() {
    3. @Override
    4. public void run() {
    5. // ...
    6. }
    7. });
    8. }
  2. 选中new Runnable(){}代码块,Refactor,Extract Field。

    1. private Runnable mRunnable;

    2. void f() {

    3. mRunnable = new Runnable() {

    4. @Override

    5. public void run() {

    6. // ...

    7. }

    8. };

    9. setRunnable(mRunnable);

    10. }

  3. Extract默认不会改变代码逻辑,Runnable的实例化和赋值还是在方法中,可以选择Intentions,Move assignment to field declaration,将赋值移到Field声明的地方。

    1. private Runnable mRunnable = new Runnable() {

    2. @Override

    3. public void run() {

    4. // ...

    5. }

    6. };

    7. void f() {

    8. setRunnable(mRunnable);

    9. }

举例:批量替换Deprecated方法

  1. 历史代码中,实现了一个Log工具类,且代码中有大量的调用。

  2. 之后发现老的工具类定义不合理,打Log时不能指定Tag,于是新实现了一个Log工具类,并将原有的方法标记为Deprecated。

    1. void f1() {

    2. deprecated_log("my_msg_1");

    3. }

    4. void f2() {

    5. deprecated_log("my_msg_2");

    6. }

    7. // ...

    8. @Deprecated

    9. void deprecated_log(String msg) {

    10. Log.d("old_tag", msg);

    11. }

    12. void log(String tag, String msg) {

    13. Log.d(tag, msg);

    14. }

  3. 现在想把老的工具类调用全部替换成新的工具类。手工替换非常繁琐而且容易出错,但是使用Inline可以很快解决问题。

  4. 步骤一:修改deprecated方法,让其调用新的工具类。

    1. @Deprecated
    2. void deprecated_log(String msg) {
    3. log("old_tag", msg);
    4. }
  5. 步骤二:选中deprecated方法调用的位置,Inline,选择Inline all invocations and remove the method,确认,则所有Deprecated方法都会被内联成新的工具方法。

Refactor Members

  • Push Members Up
  • Pull Members Down

举例:写了一个Class,现在想将其中一些方法抽取成接口

  1. class implements MyInterface
  2. 自动补全,创建MyInterface
  3. Pull Members Up
  4. 选中新建的接口,勾选要抽取的方法
  5. Done

TODO

代码注释中增加TODO,在IDEA中默认会显示成蓝色;在TODO窗口中可以看到所有的TODO,且可以设置Scope过滤。

应用场景举例

  • 在重构老代码时特别有用,因为有很多小的点,可能在新的代码结构中一时不好实现,可以加个TODO后期再完成。

  • 需求开发过程中有一些需要等待确认的点,可以先写一个TODO。

  • 开发过程中用代码实现了一些假数据,开发完了要删掉,可以写一个TODO避免后面忘记删。

Debug

Attach

对于设备上已经运行的Debug版App,点击Attach debugger to Android process,选择进程即可调试,不需要重新编译安装。如果改动的代码和被调试代码无关且不影响行号,也不需要重新编译安装。

变量

修改变量值

在Variables窗口会显示当前所有变量,右击变量 - Set Value,可以直接修改值。

查看变量和表达式的值

在Watches窗口点加号,可以添加和查看变量、表达式的值。点击Show watches in variables tab按钮,可以切换Watches显示成独立窗口,还是和Variables显示在一起。

断点

查看断点

点击View Breakpoints可以查看所有断点,快速启用、禁用、删除断点。

禁用断点

点击Mute Breakpoints,可以临时快速禁用所有断点。

变量断点、方法断点

单击成员变量、方法定义行的左侧,可打变量断点、方法断点。只要有对变量、方法的访问,就会断点。

条件断点

单击代码左侧可以打断点,右击红色断点标志,在弹窗的Condition中输入返回boolean的表达式,即可作为条件断点,当表达式成立时就会断点

Gradle

Gradle Sync

Android Studio中,会通过Gradle Sync的过程,下载更新所有依赖项,将JAR/AAR源码或class关联到工程,输出到build/generated目录,建立起代码之间的关联,从而实现代码跳转、补全等功能。

从Gradle Console的输出可以看到,实际执行的是prepareComXxxgenerateXxx等Gradle Task。

除了修改Gradle脚本、编译,Sync操作也可以直接点击工具栏或Gradle Projects窗口中的按钮触发。

Run Configurations

点击运行的三角形时,默认会执行编译(gradle assemble)、安装(gradle install)等操作,可以在Edit Configurations窗口中,指定同时要执行的其他Gradle任务,如图。

Version Control

Version Control包括git、CVS等版本控制工具(以插件形式安装),以及Android Studio自带的版本控制(代码修改的撤销等)。

  • Preferences - Version Control:可设置IDE保存的可以回退的历史记录条数,还有常用的git项目关联。

  • 关联git后,右击代码窗口左侧 - Annotate,可以查看最近的git修改记录。

  • 更多git功能可以在Main Menu - VCS - git中找到。