美文网首页软件快捷键Android开发录半栈工程师
分享两个提高效率的AndroidStudio小技巧

分享两个提高效率的AndroidStudio小技巧

作者: 请叫我大苏 | 来源:发表于2018-03-31 00:50 被阅读5221次

    本篇文章已授权微信公众号 hongyangAndroid (鸿洋)独家发布

    这次分享两个 Android Studio 的小技巧,能够有效提高效率和减少犯错,尤其是在团队协作开发中。

    1. Getter 模板修改--自动处理 null 判断
    2. 格式化代码自动整理方法位置--广度 or 深度

    好了,下面优先介绍下这两个小技巧有什么作用,然后再给出使用教程,想直接看教程的可以直接跳到最后。

    目的

    1. Getter 模板修改

    开发过程中,经常会遇到空指针异常,尤其是在线上 bug 中,由于未进行 null 判断处理导致的 bug 比例肯定不低。

    另外,model 层经常需要根据服务端接口返回的数据结构进行建模,实体类中常见的有 String 类型和 List 类型的字段。而服务端的接口文档里通常都会说明哪些字段不会为空,所以移动端建模后使用相应的实体类数据时,很少或者说会经常性忘记去做 null 判断处理。

    正常场景下,也许测不出 null 异常的问题,但如果服务器出了问题,返回了错误的数据,或者在某些特殊的场景下,某些字段的值偏偏就是 null,那么此时如果在使用的地方没有进行 null 判断处理,经常就会有问题出现,如果 app 刚好又有缓存策略,那么可能会导致特别严重的问题。

    鉴于此,我是建议,在建模创建实体类时,如果有 String 类型和 List 类型的变量时,这些类型的 getXXX() 方法中直接进行 null 判断处理,确保不会返回 null 值,这样外部使用时就不用再去进行 null 判断处理。如下:

    private String mString;
    private List<String> mList;
    
    //如果String类型的字段为空,那么返回"",外部在使用getString().equal()等之类方法时如果忘记进行null判断,也不会造成空指针异常
    public String getString() {
        return mString == null ? "" : mString;
    }
    //如果List类型字段为空,那么返回空列表。外部在使用getList().get(i)或者getList().size()等时如果忘记进行null判断,也不会造成空指针异常
    public List<String> getList() {
        if (mList == null) {
            return new ArrayList<>();
        }
        return mList;
    }
    

    这样处理的好处是统一在实体类内部进行 null 判断处理,外部使用的地方无需再一个个的去进行 null 判断处理,如果外部使用时忘记进行 null 判断处理,也不会导致空指针异常。

    但,如果每次创建完实体类后都靠开发人员的主观意识来为对应的 getXXX() 方法增加相应的 null 判断处理代码,很不靠谱。一切靠主观意识来遵守的规范都不靠谱,总会由于各种原因,如任务赶,太久未接触等等而忘记。

    所以,推荐 getXXX() 方法都通过 Android Studio 来自动生成相应代码,那么,就可以通过修改 AS 的 Getter 方法的模板文件,来达到自动生成相应的 null 判断处理代码,以工具代替手工,一提供效率,二强制遵守规范,三解决靠主观意识不靠谱问题。


    1. 格式化代码自动整理方法位置

    当 app 经过越来越多的迭代,增加越来越多的功能时,项目难免会逐渐庞大起来,有些类里的代码会渐渐多了起来。

    为了易于阅读,通常对类里的代码会根据各自的职能划分到一个个方法中,尽量遵守方法的单一职责,这样一来,各个方法之间难免会有关联关系,a 方法调用了 b,c 方法,b 方法调用了 d 方法,等等。

    这么多的方法,如果不按照一定的规范来整理、摆放的话,当类里的方法越来越多时,这些方法位置杂乱无章的摆放会给 review 人员的阅读,或者过了很长一段时间后本人回来自己阅读时造成一定的障碍。

    常见的是规范有一种是按照权限来归纳整理,private 方法集中在一起,public 方法集中在一起。

    还有一种规范是按照就近原则摆放,a 方法调用了 b 方法,那么 b 方法位置就尽量靠近 a,我个人倾向于这一种规范,这样在熟悉一个类里的代码时,从上往下慢慢过下来即可,不同跳过来跳过去的。

    那么,同样的问题,靠开发人员的主观意识来遵守这种规范是很不靠谱的。写代码过程中,新建了一个方法时,并不会特别特意的去考虑要将它放在哪,基本就是就近放,这样也还好,还算稍微有些关联,有些顺序。

    但,如果是在后期新增功能,在旧代码中又去新建方法时,如果对这个类不熟悉,这时候通常都不会去仔细的考虑新写的方法应该要放在哪,要么就是放最后,要么随手就近,久而久之,类里的方法就会越来越杂乱无章。

    所以,一切靠主观意识来遵守规范的行为都不靠谱。

    鉴于此,推荐打开 Android Studio 自动整理方法位置的功能,借助工具来遵守规范,提高效率的同时也能写出优美的代码。

    教程

    Getter模板修改教程

    1. 随便建个类,写几个属性,然后按快捷键 Alt + Insert 或在代码区域 右键 -> Generate -> Getter,然后会有一个弹框:
    第一步
    1. 此时先不要点击 OK 键,先点击右上角的 的图标,来修改模板文件:
    第二步.png
    1. 此时只有一份 AS 默认的生成 Getter 方法的模板,要对这份模板进行修改,所以接下去可以选择新建一份新的模板文件或者在原文件上修改都可以,比如我新建了一份 NotNull_getter 模板文件:
    第三步
    1. 模板文件需要修改的地方就仅仅是在$(name){…} 代码块里的 return 生成规则,原本规则是统一返回字段值本身,根据规范新增两条规则:增加 String 类型和 List 类型的生成规则。以下是修改后的整个模板文件代码,可以拷贝过去直接使用:
    #if($field.modifierStatic)
    static ##
    #end
    $field.type ##
    #set($name = $StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project))))
    #if ($field.boolean && $field.primitive)
      #if ($StringUtil.startsWithIgnoreCase($name, 'is'))
        #set($name = $StringUtil.decapitalize($name))
      #else
        is##
    #end
    #else
      get##
    #end
    ${name}() {
      #if ($field.string)
         return $field.name == null ? "" : $field.name;
      #else 
        #if ($field.list)
        if ($field.name == null) {
            return new ArrayList<>();
        }
        return $field.name;
        #else 
        return $field.name;
        #end
      #end
    }
    
    1. 建完新模板文件后点击 OK 键,以后通过右键 -> Generate -> Getter 来生成 getXXX() 方法时,注意一下模板文件选择是否正确,一般首次选择后以后都是默认上一次的:
    第五步
    1. 效果,getXXX() 方法都是 AS 自动生成,而且根据修改后的模板,也能保证 String 类型和 List 类型都不会返回null值。
    效果

    格式化代码自动整理方法位置教程

    1. 先开启自动整理方法位置的功能,位置:
      File -> Settings -> Editor -> Code Style -> Java -> Arrangement
    功能开启

    如上图的 2,3 点功能,默认都是关闭的。

    第 2 点功能:Keep overridden methods together – keep order

    意思是将由 override 标志的方法都集中放置,建议将此功能开启,override 的方法通常要么是系统的一些回调方法,要么是我们自己定义的一些接口,这部分方法本身就有一定的关联性,集中在一起很合理。

    注意,AS支持两种规则,一种是 keep order(按原有顺序),一种是 order by name(按照方法字母表顺序)。至于哪一种较合适,个人喜好,我是选择的 keep order。

    第3点功能:Keep dependent methods together

    意思是将相关的方法按照某则规则放在一起,AS支持两种规则:

    breadth-first order & depth-first order

    我的理解,说得通俗点也就是广度优先和深度优先,这个功能建议开启。

    举个例子,假设一个类里有这么几个方法,a 调用了 b, c, d, 而 b 调用了 e, f,如果是按照广度优先来整理这些方法的位置时,breadth-first order:

    广度优先

    广度优先整理后的方法顺序:a, b, c, d, e, f。也就是说,方法 a 里面调用了三个方法,那么优先将这三个方法摆放在方法 a 下方,此时并不去考虑这三个方法里是否还调用了其他方法。等过完方法 a,那么以同样的道理再去整理方法 b 中调用的方法的位置。

    但如果是深度优先,那么整理后的方法顺序就不同了,如下,depth-first order:

    深度优先

    深度优先整理后的方法顺序:a, b, e, f, c, d。也就是说,方法 a 内调用了三个方法,第一个方法是 b, 然后方法 b 又调用了 e, f。所以方法 b 紧接着 a 方法下面摆放,方法 e, f 紧接着方法 b 下面摆放,直到 e, f 里都没有其他方法了。然后再重新回到方法 a 内继续往下过方法 c 的位置,以此类推。

    两种规则有各自的好处,广度优先侧重于优先梳理每个方法的大体工作;而深度优先则侧重于梳理每个方法的实现细节,流程步骤;

    目前我是选择广度优先,因为我更侧重于关注每个方法大体的工作,对于一个不熟悉的方法,大概过一下它里面的每个方法大体上做了什么,就能大概理解这个方法的大体工作。

    1. 以上仅仅只是开启功能而已,而要借助 Android Studio 来自动整理方法位置,就是通过 AS 的格式化代码功能,快捷键也就是 Ctrl + Alt + L 。但这个格式化操作默认是没有启动对方法进行整理的操作的,每次按完快捷键后会有如下提示:
    功能开启2

    重点在底部那行灰色的字体,通过快捷键 Ctrl + Alt + Shift + L 可以打开配置 dialog:

    配置

    Rearrange code 默认是没有勾选的,所以想要启用整理方法的功能,需要将这个勾选上,以后在通过 Ctrl + Alt + L 来格式化代码时,AS 就会根据我们在第一个步骤中设定的规则来自动整理方法的位置。


    QQ图片20180316094923.jpg

    最近(2018-03)刚开通了公众号,想激励自己坚持写作下去,初期主要分享原创的Android或Android-Tv方面的小知识,准备可能还有点不足,感兴趣的可以先点一波关注,谢谢支持~~

    相关文章

      网友评论

      • sweetying:简单易学, 而且很实用,给楼主点赞:smile:
      • 请叫我财迷:两个功能都超赞
      • Raininsky:写的很好,赞一个:+1:
      • 呆T_T呆:功能很实用,谢谢
      • lsqbeyond:现在按照如上方法修改,但是使用Gsonformat生成的get还是没有判断,这的非空判断您知道怎么添加吗?
        请叫我大苏:@lsqbeyond Gsonformat是AS的一个插件,所以它自动生成代码是按照插件定的规范来的。那就需要修改插件的模板或者插件的源码,郭霖今天(4-11)公众号推荐的文章刚好是这方面的内容,感兴趣可以自己看看,这方面我还没研究,有时间会去看看,目前还不懂怎么解决
      • 2d65ff9943d6:感谢,也写得非常好。坚持最难,请坚持下去。
        请叫我大苏:@CodeWorld 谢谢:blush: ,我会坚持的,这段时间很忙,但忙之中也有更多可以记录下来的
      • wo叫天然呆:第一个挺好的
        第二个用得不是很习惯
      • 554cb745d1a4:为什么get方法提示错误。。。
        请叫我大苏:@一撇一捺默写挂念 私聊把生成的代码发过来看看,哪里出错了
      • _cxcc:private String status;
        private DataBean data;

        这种情况 这个对象可以判空吗?
        请叫我大苏:@f3ee9f61299d 目前我也仅仅知道string,list类型如何判断。既然这样,等忙过这段时间,我抽空研究看看~~,先提一个思路,试试$field.int 这样是不是代表int类型,如果几个基本类型都知道如何判断的话,那么也许可以通过排除基本类型外其余的就都当做是对象来处理了
        灰太狼_zq:@请叫我大苏 作者你好,我也需要此功能,但是不知道怎么进行判断,无法搜索到相关的资料文档
        请叫我大苏:@_cxcc 自定义的对象么?应该是可以的,没还去研究
      • 请叫我大苏:@BeyondWorlds kotlin不行,第二个配置是只设置java代码的
      • BeyondWorlds:那个格式化方法的,好像使用kotlin的没用,只有java写的代码才可以。。
        请叫我大苏:@BeyondWorlds 对啊,因为配置是进入的code style -> java 里进行设置的,所以只支持java。kotlin有没有相关的配置就不清楚了
      • Cpb:感谢分享
      • 糊涂的七小宝:我是特地过来注册账号来表达感谢的
        请叫我大苏:@糊涂的七小宝 :blush: 谢谢,功能实用就好
      • A_si:刚读完英文版,今天你发了翻译版,如果英文版不是你写的,请注明出处和翻译。
        请叫我大苏:@A_si :disappointed_relieved: 表示从没看过什么英文版的,本篇是自己一个个字打出来的,100%原创,也许介绍的两个小功能已经有其他人写过,但文字表达方面肯定是自己写的。英文版地址能否麻烦发一下,看看
      • seawaveai:学习了,特别是第一个判读Null的很方便。 请问这语法是怎么看懂的!
        seawaveai:@请叫我大苏 OK,明白了。
        请叫我大苏:@seawaveai :joy: 我也看不懂,从结论往回推的。首先已经知道AS默认的Get方法生成之后的代码长啥样了,所以去模板文件里找相应关键字,做些假设再随便修改些地方,实践下,很快就能找到关键的地方,该怎么改了。
      • 陌上丿花已开:微信跑来看看
        请叫我大苏:@陌上丿花已开 :blush: 谢谢
      • leilifengxingmw:专门登录来点赞:grin:
        请叫我大苏:@humanheima :blush: 谢谢
      • mrzhqiang:666,用 Optional<T>

      本文标题:分享两个提高效率的AndroidStudio小技巧

      本文链接:https://www.haomeiwen.com/subject/ukvwcftx.html