前言
以下建议是结合自身经验与网上多篇博客总结而成

  1. 控制好每一张图片的大小,因为它们将影响apk的体积(和UI多交流),以下提供一些压缩图片的网站。

    众所周知的熊猫压缩
    智图是腾讯ISUX前端团队开发的一个专门用于图片压缩和图片格式转换的平台,其功能包括针对png,jpeg,gif等各类格式图片的压缩,以及为上传图片自动选择最优的图片格式。同时,智图平台还会为用户转换一份webp格式的图片
    ImageAlpha通过应用有损压缩和转换为更高效的PNG8 + alpha格式,大大减少了24位PNG文件的文件大小(包括Alpha透明度)
    Imageoptim无损压缩,并且支持客户端(Mac客户端)
    SquooshGoogle 开源发布的一款专门用来压缩图片的在线服务,除了压缩尺寸,还能进行简单的编辑,包括剪裁、减少调色板

  2. 如果页面跳转之间需要传递大量数据,那么并不建议使用Intent或者Bundle,而是采用RxBus、EventBus、LiveDataBus等。这里着重推荐LiveDataBus。但不能滥用

  3. 采用 PBF(按功能分包 Package By Feature)参考Blankj的Android开发规范
  4. 布局尽量避免嵌套,妥善使用ConstraintLayout、Include、ViewStub、Merge,关注Space标签。这里推荐郭霖大神的(Android新特性介绍,ConstraintLayout完全解析
  5. 选择开源库要慎重;不要只为某个小功能而导入一个体积庞大的库
  6. 使用一些辅助工具来检测项目的内存溢出、性能检测、异常报告系统等情况。推荐一些轮子(工具众多,自行选择)

    Bugly腾讯Bugly,为移动开发者提供专业的异常上报和运营统计,帮助开发者快速发现并解决异常,同时掌握产品运营动态,及时跟进用户反馈
    BlockCanary是一个Android平台的一个非侵入式的性能监控组件
    LeakCanary内存泄漏检测库

  7. 使用依赖注入解耦!!!解耦!!!解耦!!!Dagger2 on Android; 实际上:依赖注入不是必须的,有“条件”可用上(2021.07.22)

  8. 别往Application写一些无用代码,保持它的简洁,不然会拖慢应用初始化和启动速度
  9. 尽量避免使用数据库,除非真需要
  10. 使用DialogFragment而不是Dialog,官方解释
  11. 不要过多使用枚举,它占用的内存空间要比整数大(辟谣:枚举是可以使用的,详情
  12. 使用一些Android特有的数据结构,比如SparseArrayArrayMap等,它们具有更好的性能
  13. 适当使用软引用和弱引用,官方解释
  14. 使用线程池而非创建大量的线程;参考:Android 线程和线程池一篇就够了
  15. 适当的添加注释!! 适当的添加注释!!!适当的添加注释!!!
  16. 别在ViewonDraw方法里面创建对象或者做耗时任务
  17. 别把Context或者View此等对象设置成静态
  18. 尽量采用静态内部类,可避免潜在由于内部类导致的内存泄漏
  19. 有一套良好的开发规范;参考:Android开发规范
  20. 代码要有层次感,遵循单一职责,参考:设计模式六大原则(1):单一职责原则

2021.07.22更新

  1. 只有最合适的架构;没有最好的架构。新技术始终会变成旧技术,结合条件、环境等因素寻找最合适的架构

  2. 学习Kotlin

  3. ViewBinding是代替findViewById的一个好工具
  4. 遇到双层列表的需求时:使用Recycleview+自定义LinearLayout动态添加View的方式来代替Recycleview嵌套Recycleview也可以
  5. 基于第20点,当一个页面太复杂时,按功能拆分防止Activity/Fragment过于臃肿
  6. 一些日志埋点是很有必要的。但并不包含一些敏感信息的日志(如:token,userId数据类的日志或者网络报文日志)
  7. 可用注解代替枚举
    1. @IntDef({Type.ONE, Type.TWO})
    2. @Retention(RetentionPolicy.SOURCE)
    3. public @interface Type {
    4. int ONE = 1;
    5. int TWO = 2;
    6. }

2022.04.26更新

  1. 被标记lateinit的类或者变量,在线上复杂环境下依然可能没有初始化而报错UninitializedPropertyAccessException。对此使用时应考虑到异常,并且在需要时用isInitialized判断 ```kotlin private lateinit var mTest: String

if (this::mTest.isInitialized) {

} ```

  1. 如果希望只内联一部分传给内联函数的 lambda 表达式参数,那么可以用 noinline 修饰符标记不希望内联的函数参数:

    inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) { …… }

  2. 内联对性能的预期影响是微不足道的。内联最适合具有函数类型参数的函数