阿里巴巴Android开发手册读后笔记
通过前边一段时间的阅读,把手册中的内容整理了一下,做了一篇读后笔记。 个人觉得以下内容是在开发中需要注意的。
这里放个链接,是阿里巴巴开发手册 ,需要的可以去下载
Android 基础组件
1.【强制】Activity 间的数据通信,对于数据量比较大的,避免使用 Intent + Parcelable 的方式,可以考虑 EventBus 等替代方案,以免造成 TransactionTooLargeException。
2.【强制】Activity 间通过隐式 Intent 的跳转,在发出 Intent 之前必须通过 resolveActivity 检查,避免找不到合适的调用组件,造成 ActivityNotFoundException 的异常。 正例:
- *
public void viewUrl(String url, String mimeType) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), mimeType);
if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_
ONLY) != null) {
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
if (Config.LOGD) {
Log.d(LOGTAG, "activity not found for " + mimeType + " over " +
Uri.parse(url). getScheme(), e);
}
}
}
}
3.【强制】避免在 Service#onStartCommand()/onBind()方法中执行耗时操作,如果确
实有需求,应改用 IntentService 或采用其他异步机制完成。4.【推荐】不要在 Activity#onDestroy()内执行释放资源的工作,例如一些工作线程的
销毁和停止,因为 onDestroy()执行的时机可能较晚。可根据实际需要,在
Activity#onPause()/onStop()中结合 isFinishing()的判断来执行。5.【推荐】对于只用于应用内的广播,优先使用 LocalBroadcastManager 来进行注册
和发送,LocalBroadcastManager 安全性更好,同时拥有更高的运行效率。
说明:
对于使用 Context#sendBroadcast()等方法发送全局广播的代码进行提示。如果该广
播仅用于应用内,则可以使用 LocalBroadcastManager 来避免广播泄漏以及广播被
拦截等安全问题,同时相对全局广播本地广播的更高效。- 6.【推荐】当前Activity的onPause方法执行结束后才会执行下一个Activity的onCreate
方法,所以在 onPause 方法中不适合做耗时较长的工作,这会影响到页面之间的跳
转效率。 - 7.【强制】不要在 Android 的 Application 对象中缓存数据。基础组件之间的数据共享
请使用 Intent 等机制,也可使用 SharedPreferences 等数据持久化机制。 - 8.【强制】使用 Adapter 的时候,如果你使用了 ViewHolder 做缓存,在 getView()的
方法中无论这项 convertView 的每个子控件是否需要设置属性(比如某个 TextView
设置的文本可能为 null,某个按钮的背景色为透明,某控件的颜色为透明等),都需
要为其显式设置属性(Textview 的文本为空也需要设置 setText(“”),背景透明也需要
设置),否则在滑动的过程中,因为 adapter item 复用的原因,会出现内容的显示错
乱。 - 9.【强制】Activity或者 Fragment 中动态注册BroadCastReceiver 时,registerReceiver()
和 unregisterReceiver()要成对出现。
说明:
如果 registerReceiver()和 unregisterReceiver()不成对出现,则可能导致已经注册的
receiver 没有在合适的时机注销,导致内存泄漏,占用内存空间,加重 SystemService
负担。
部分华为的机型会对 receiver 进行资源管控,单个应用注册过多 receiver 会触发管
控模块抛出异常,应用直接崩溃。
UI部分
- 10.【推荐】尽量不要使用 AnimationDrawable,它在初始化的时候就将所有图片加载
到内存中,特别占内存,并且还不能释放,释放之后下次进入再次加载时会报错。
说明:
Android 的帧动画可以使用 AnimationDrawable 实现,但是如果你的帧动画中如果
包含过多帧图片,一次性加载所有帧图片所导致的内存消耗会使低端机发生 OOM
异常。帧动画所使用的图片要注意降低内存消耗,当图片比较大时,容易出现 OOM。 - 11.【强制】不能使用 ScrollView 包裹 ListView/GridView/ExpandableListVIew;因为这
样会把 ListView 的所有 Item 都加载到内存中,要消耗巨大的内存和 cpu 去绘制图
面。
说明:
ScrollView 中嵌套 List 或 RecyclerView 的做法官方明确禁止。除了开发过程中遇到
的各种视觉和交互问题,这种做法对性能也有较大损耗。ListView 等 UI 组件自身有
垂直滚动功能,也没有必要在嵌套一层 ScrollView。目前为了较好的 UI 体验,更贴
近 Material Design 的设计,推荐使用 NestedScrollView
进程、线程与消息通信
- 12.【强制】新建线程时,必须通过线程池提供(AsyncTask 或者 ThreadPoolExecutor
或者其他形式自定义的线程池),不允许在应用中自行显式创建线程。
说明:
使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解
决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。另外创建匿名线程不便于后续的资源使用分析,
对性能分析等会造成困扰。 - 13.【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方
式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors 返回的线程池对象的弊端如下:
1) FixedThreadPool 和 SingleThreadPool : 允 许 的 请 求 队 列 长 度 为
Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM;
2) CachedThreadPool 和 ScheduledThreadPool : 允 许 的 创 建 线 程 数 量 为
Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。 - 14.【推荐】谨慎使用 Android 的多进程,多进程虽然能够降低主进程的内存压力,但会
遇到如下问题:
1) 不能实现完全退出所有 Activity 的功能;
2) 首次进入新启动进程的页面时会有延时的现象(有可能黑屏、白屏几秒,是白
屏还是黑屏和新 Activity 的主题有关);
3) 应用内多进程时,Application 实例化多次,需要考虑各个模块是否都需要在所
有进程中初始化;
4) 多进程间通过 SharedPreferences 共享数据时不稳定。
文件与数据库
动画资源
- 1.【推荐】在有强依赖 onAnimationEnd 回调的交互时,如动画播放完毕才能操作页
面 , onAnimationEnd 可 能 会 因 各 种 异 常 没 被 回 调 ( 参 考 :
https://stackoverflow.com/questions/5474923/onanimationend-is-not-getting-calle
d-onanimationstart-works-fine ), 建 议 加 上 超 时 保 护 或 通 过 postDelay 替 代
onAnimationEnd。
View v = findViewById(R.id.xxxViewID);
final FadeUpAnimation anim = new FadeUpAnimation(v);
anim.setInterpolator(new AccelerateInterpolator());
anim.setDuration(1000);
anim.setFillAfter(true);
new Handler().postDelayed(new Runnable() {
public void run() {
if (v != null) {
v.clearAnimation();
}
}
}, anim.getDuration());
v.startAnimation(anim);
安全
- 1.【强制】将 android:allowbackup 属性设置为 false,防止 adb backup 导出数据。
说明:
在 AndroidManifest.xml 文件中为了方便对程序数据的备份和恢复在 Android API
level 8 以后增加了 android:allowBackup 属性值。默认情况下这个属性值为 true,故
当 allowBackup 标志值为 true 时,即可通过 adb backup 和 adb restore 来备份和恢
复应用程序数据。 - 3.【强制】META-INF 目录中不能包含如.apk,.odex,.so 等敏感文件,该文件夹没有经
过签名,容易被恶意替换。 - 4.【强制】Receiver/Provider 不能在毫无权限控制的情况下,将 android:export 设置
为 true。 - 5.【强制】不要广播敏感信息,只能在本应用使用 LocalBroadcast,避免被别的应用
收到,或者 setPackage 做限制。 - 6.【强制】应用发布前确保 android:debuggable 属性设置为 false
- 7.【强制】密钥加密存储或者经过变形处理后用于加解密运算,切勿硬编码到代码中。
说明:
应用程序在加解密时,使用硬编码在程序中的密钥,攻击者通过反编译拿到密钥可
以轻易解密 APP 通信数据。 - 8.【强制】将所需要动态加载的文件放置在 apk 内部,或应用私有目录中,如果应用
必须要把所加载的文件放置在可被其他应用读写的目录中(比如 sdcard),建议对不
可信的加载源进行完整性校验和白名单处理,以保证不被恶意代码注入。 - 9.【强制】除非 min API level >=17,请注意 addJavascriptInterface 的使用。
说明:
API level>=17,允许 js 被调用的函数必须以@JavascriptInterface 进行注解,因此
不受影响; 对于 API level < 17,尽量不要使用 addJavascriptInterface,如果一定
要用,那么:
1) 使用 https 协议加载 URL,使用证书校验,防止访问的页面被篡改挂马;
2) 对加载 URL 做白名单过滤、完整性校验等防止访问的页面被篡改;
3) 如果加载本地 html,应该会 HTML 内置在 APK 中,以及对 HTML 页面进行完整
性校验。 - 10.【强制】使用 Android 的 AES/DES/DESede 加密算法时,不要使用默认的加密模式
ECB,应显示指定使用 CBC 或 CFB 加密模式。
说明:
加密模式 ECB、CBC、CFB、OFB 等,其中 ECB 的安全性较弱,会使相同的铭文
在不同的时候产生相同的密文,容易遇到字典攻击,建议使用 CBC 或 CFB 模式。
1) ECB:Electronic codebook,电子密码本模式
2) CBC:Cipher-block chaining,密码分组链接模式
3) CFB:Cipher feedback,密文反馈模式
4) OFB:Output feedback,输出反馈模式
总结
手册中一般对于某项开发的内容都写的有强制,推荐,参考三个等级, 个人觉得一般情况下按照强制执行的都是一些必要的, 能够对开发有避免采坑的意见和建议,很中肯。