该笔记主要记录本人在读《阿里巴巴Adroid开发手册》的过程,自我感觉有疑惑或者值得记录的地方。故并非对所有内容都有涉略。有兴趣的朋友可以当作一个参考内容来看看。主要按该手册的章节进行阅读,记录。后续有新的感悟还会补充。

二、Android资源文件命名与使用

【自我感悟】1. Java按一定的规律来命名控件。做到多module时资源不会冲突以及模块命名定义清晰。

三、Android 基本组件

1【强制】Activity 间的数据通信,对于数据量比较大的,避免使用 Intent + Parcelable 的方式,可以考虑 EventBus 等替代方案,以免造成 TransactionTooLargeException。
其他还可以搞个静态内部类或者单例来保存数据,在一个activity存,另一个取。这些方法本质上都是开辟一块公共区域来存取数据。
(猜测前一个Activity的onStop中用EventBus发送数据,另一个目标Activity的onCreate中对EventBus进行注册)
2.【强制】避免在 BroadcastReceiver#onReceive()中执行耗时操作,如果有耗时工作, 应该创建 IntentService 完成,而不应该在 BroadcastReceiver 内创建子线程去做。
【原因】因为BroadcastReceiver生命周期很短,一旦结束,其所在进程就属于空进程(没有任何活动组件的进程),极易在系统内存不足时优先被杀死,而正在工作的子线程也会被杀死。所以,推荐开启一个service,将耗时操作交给service,这样可以提高宿主进程优先级,保证耗时操作执行完成。
3.【推荐】当前 Activity 的 onPause 方法执行结束后才会执行下一个 Activity 的 onCreate 方法,所以在 onPause 方法中不适合做耗时较长的工作,这会影响到页面之间的跳 转效率。
4.对于只用于应用内的广播,优先使用 LocalBroadcastManager 来进行注册 和发送,LocalBroadcastManager 安全性更好,同时拥有更高的运行效率。
【原因】LocalBroadcastManager只在app内进行广播,不会在各app之间进行传播。可防止自己的广播信息被别有用心的人监听。(跨Activity数据传递本质上是找了一个公共区域用来存放数据)

四、UI 与布局

1. 【强制】布局中不得不使用 ViewGroup 多重嵌套时,不要使用 LinearLayout 嵌套,改用 RelativeLayout,可以有效降低嵌套数。
【原因】同一个布局在很多情况下RelativeLayout下的布局所需的层次会小于LinearLayout所需的布局可减少过度绘制。但是在布局相同的情况下用LinearLayout更加好。因为RelativeLayout会进行上下和左右两次measure
2.【推荐】在 Activity 中显示对话框或弹出浮层时,尽量使用 DialogFragment,而非 Dialog/AlertDialog,这样便于随 Activity 生命周期管理对话框/弹出浮层的生命周期。
3.【推荐】文本大小使用单位 dp,view 大小使用单位 dp。对于 Textview,如果在文 字大小确定的情况下推荐使用 wrap_content 布局避免出现文字显示不全的适配问 题。
【原因】sp会随着用户在设置中设置系统大小不同而变化。字体变化后有可能导致app适配的问题。同时国内的rom碎片化也有可能导致各种显示问题。而dp会一直保持现有大小。但是这个的弊端是用户调整系统的字体大小后,你自身app的大小不能进行变化。有点违背系统的感觉。个人感觉用哪个根据自己需要吧。目前我还是用的sp
4.【推荐】不能在 Activity 没有完全显示时显示 PopupWindow 和 Dialog。
【原因】PopupWindow不像对话框那样从屏幕的固定位置弹出,而是依赖于锚点控件对象的位置,所谓锚点控件对象,就是界面组件中的某个控件,PopupWindow的展示和功能都是以它为核心,作为锚点控件的扩展交互界面,以增强该控件对象的功能。弹出窗口与描点控件有着紧密的联系,在构造并展示弹出窗口前,需要保证锚点控件所在的控件树已经与窗口管理服务建立连接,因为在弹出窗口的展示过程中,需要通过该窗口对象来获取相关信息。在界面组件的构造过程中,窗口连接的建立是个异步过程,也就是说,当Activity.onCreate()等函数被调用时,界面与窗口管理服务的双向通信连接尚未建立,如果在此时构造弹出窗口则会抛出异常。因此,如果期望在界面组件展现之处便构造弹出窗口,可以将弹出窗口对象构造也转换成一个异步过程。即view.post(new running()).
5.【强制】不能使用 ScrollView 包裹 ListView/GridView/ExpandableListVIew;因为这 样会把 ListView 的所有 Item 都加载到内存中,要消耗巨大的内存和 cpu 去绘制图 面。
说明:ScrollView 中嵌套 List 或 RecyclerView 的做法官方明确禁止。除了开发过程中遇到的各种视觉和交互问题,这种做法对性能也有较大损耗。ListView 等 UI 组件自身有垂直滚动功能,也没有必要在嵌套一层 ScrollView。目前为了较好的 UI 体验,更贴近 Material Design 的设计,推荐使用 NestedScrollView
PS:本人测试NestedScrollView中添加ListView也会全部添加。类似于要使用这种需求。可以用阿里的Vlayout布局。或者ListView添加HeadView等。

五、进程、线程与消息通信

1.【强制】不要通过 Intent 在 Android 基础组件之间传递大数据(binder transaction 缓存为 1MB),可能导致 OOM。
2.【强制】新建线程时,必须通过线程池提供(AsyncTask 或者 ThreadPoolExecutor 或者其他形式自定义的线程池),不允许在应用中自行显式创建线程。
【原因】本人在开发app中发现如果多人一起开发并且都个人创建线程则会导致app内线程乱飞。严重的如华为的某些机制在线程数达到500时会导致crash。建议根据业务定义几个全局统一的线程库。
3.【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方 式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
4.【强制】不要在非 UI 线程中初始化 ViewStub,否则会返回 null。

六、文件与数据库

1. 【强制】任何时候不要硬编码文件路径,请使用 Android 文件系统 API 访问。
android.os.Environment#getExternalStorageDirectory() android.os.Environment#getExternalStoragePublicDirectory() android.content.Context#getFilesDir() android.content.Context#getCacheDir
2.【推荐】SharedPreference 提交数据时,尽量使用 Editor#apply(),而非 Editor#commit()。一般来讲,仅当需要确定提交结果,并据此有后续操作时,才使 用 Editor#commit()。
说明:SharedPreference 相关修改使用 apply 方法进行提交会先写入内存,然后异步写入 磁盘,commit 方法是直接写入磁盘。如果频繁操作的话 apply 的性能会优于 commit,apply 会将最后修改内容写入磁盘。但是如果希望立刻获取存储操作的结果,并据此做相应的其他操作,应当使用 commit.

七、Bitmap、Drawable 与动画

这节讲到的内容基本上都有所了解。所以不做记录了。主要就是要注意不要OOM。

八、安全

1.不要把敏感信息打印到 log 中.
【方法】在产品的线上版本中关闭调试接口,不要输出敏感信息。方法参考 https://mp.weixin.qq.com/s/DE4gr8cTRQp2jQq3c6wGHQ 黑科技:用Proguard的-assumenosideeffects清除log
这节的内容了解的基本都了解。有些内容真的基本没怎么涉略过。后续要好好研究一下。