2018春节刚结束,阿里为移动开发者准备了一份迟到的新年礼物——《阿里巴巴Android开发手册》,作为一个Android开发者,怎么能不学习一下呢
一.Android资源文件命名与使用
随记:养成一个良好的规范的写代码习惯还是很重要的,感兴趣的可以看一下手册的详细介绍
二.【强制】Activity 间的数据通信,对于数据量比较大的,避免使用 Intent + Parcelable 的方式,可以考虑 EventBus 等替代方案,以免造成 TransactionTooLargeException。
随记:intent传输数据如果太大,会造成TransactionTooLargeException错误
image.png
Intent intent = new Intent(this,SecondActivity.class);
DataSave.setValue(value);//将value设置到静态类DataSave中
//SecondActivity.value = value;//或则将value设置到SecondActivity的静态属性中
startActivity(intent);
第二:将传递的信息做本地存储,如SP存储、数据库等,然后在跳转对象中取出来,不会提高程序的耦合性,但是效率较低。
三:【推荐】不要在 Activity#onDestroy()内执行释放资源的工作,例如一些工作线程的 销毁和停止,因为 onDestroy()执行的时机可能较晚。可根据实际需要,在 Activity#onPause()/onStop()中结合 isFinishing()的判断来执行。
随记:这个可以对照一下Activity的生命周期,比较一下。
四:【推荐】Service 需要以多线程来并发处理多个启动请求,建议使用 IntentService, 可避免各种复杂的设置。
随记: Service 组件一般运行主线程,应当避免耗时操作,如果有耗时操作应该在 Worker线程执行。 可以使用 IntentService 执行后台任
public class SingleIntentService extends IntentService { public SingleIntentService() {
super("single-service thread"); }
@Override
protected void onHandleIntent(Intent intent) {
try {
......
} catch (InterruptedException e) { e.printStackTrace();
}
} }
五:【推荐】当前 Activity 的 onPause 方法执行结束后才会执行下一个 Activity 的 onCreate 方法,所以在 onPause 方法中不适合做耗时较长的工作,这会影响到页面之间的跳 转效率。
随记:当Activity B在Activity A前面时,会触发Activity A中的onPause方法。 B直到A的onPause方法执行完后才会被创建,所以建议不要在onPause方法中做耗时操作。
所以,onPause被触发,并不是A的主界面处于被其它东西不完全覆盖状态,而是被某个其它Activity不完全覆盖。
六:【强制】布局中不得不使用 ViewGroup 多重嵌套时,不要使用 LinearLayout 嵌套,改用 RelativeLayout,可以有效降低嵌套数。
随记:同一个布局在很多情况下RelativeLayout下的布局所需的层次会小于LinearLayout所需的布局可减少过度绘制。但是在布局相同的情况下用LinearLayout更加好。因为RelativeLayout会进行上下和左右两次measure
七:【推荐】使用 Toast 时,建议定义一个全局的 Toast 对象,这样可以避免连续显示 Toast 时不能取消上一次 Toast 消息的情况(如果你有连续弹出 Toast 的情况,避免 使用 Toast.makeText)。
随记:可以在工具类中写一个全局的toast
public static void showToast(Context context, String msg) {
if (context != null && checkNotNull(msg)) {
if (toast == null) {
toast = Toast.makeText(context.getApplicationContext(), msg, Toast.LENGTH_SHORT);
} else {
toast.setText(msg);
}
toast.show();
}
}
八:【强制】布局中不得不使用 ViewGroup 多重嵌套时,不要使用 LinearLayout 嵌套,改用 RelativeLayout,可以有效降低嵌套数。
随记:Android 应用页面上任何一个 View 都需要经过 measure、layout、draw 三个步骤才能被正确的渲染。从 xml layout 的顶部节点开始进行 measure,每个子节点都需 要向自己的父节点提供自己的尺寸来决定展示的位置,在此过程中可能还会重新measure(由此可能导致 measure 的时间消耗为原来的 2-3 倍)。节点所处位置越深,套嵌带来的 measure 越多,计算就会越费时。这就是为什么扁平的 View 结构会性能更好。
同时,页面拥上的 View 越多,measure、layout、draw 所花费的时间就越久。要缩 短这个时间,关键是保持 View 的树形结构尽量扁平,而且要移除所有不需要渲染的View。理想情况下,总共的 measure,layout,draw 时间应该被很好的控制在 16ms以内,以保证滑动屏幕时 UI 的流畅。
九:【推荐】文本大小使用单位 dp,view 大小使用单位 dp。对于 Textview,如果在文 字大小确定的情况下推荐使用 wrap_content 布局避免出现文字显示不全的适配问 题。
随记:话说国内手机厂商字体大小搞得有点乱,还是用dp吧
十:【推荐】灵活使用布局,推荐 Merge、ViewStub 来优化布局,尽可能多的减少 UI 布局层级,推荐使用 FrameLayout,LinearLayout、RelativeLayout 次之。
随记:在开发中UI布局是我们都会遇到的问题,随着UI越来越多,布局的重复性、复杂度也会随之增长, include 、merge、ViewStub堪称布局优化神器
十一:【推荐】不能在 Activity 没有完全显示时显示 PopupWindow 和 Dialog。
随记:PopupWindow不像对话框那样从屏幕的固定位置弹出,而是依赖于锚点控件对象的位置,所谓锚点控件对象,就是界面组件中的某个控件,PopupWindow的展示和功能都是以它为核心,作为锚点控件的扩展交互界面,以增强该控件对象的功能。弹出窗口与描点控件有着紧密的联系,在构造并展示弹出窗口前,需要保证锚点控件所在的控件树已经与窗口管理服务建立连接,因为在弹出窗口的展示过程中,需要通过该窗口对象来获取相关信息。在界面组件的构造过程中,窗口连接的建立是个异步过程,也就是说,当Activity.onCreate()等函数被调用时,界面与窗口管理服务的双向通信连接尚未建立,如果在此时构造弹出窗口则会抛出异常。因此,如果期望在界面组件展现之处便构造弹出窗口,可以将弹出窗口对象构造也转换成一个异步过程。即view.post(new running()).
十二:【强制】不能使用 ScrollView 包裹 ListView/GridView/ExpandableListVIew;因为这 样会把 ListView 的所有 Item 都加载到内存中,要消耗巨大的内存和 cpu 去绘制图 面。
随记:ScrollView 中嵌套 List 或 RecyclerView 的做法官方明确禁止。除了开发过程中遇到的各种视觉和交互问题,这种做法对性能也有较大损耗。ListView 等 UI 组件自身有垂直滚动功能,也没有必要在嵌套一层 ScrollView。推荐使用 NestedScrollView。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout> <android.support.v4.widget.NestedScrollView>
<LinearLayout> <ImageView/>
...
<android.support.v7.widget.RecyclerView/> </LinearLayout>
</android.support.v4.widget.NestedScrollView>
十三:【强制】不要通过 Intent 在 Android 基础组件之间传递大数据(binder transaction缓存为 1MB),可能导致 OOM。
十四:【强制】在 Application 的业务初始化代码加入进程判断,确保只在自己需要的进程初始化。特别是后台进程减少不必要的业务初始化。
随记:有时候我们会在Application中初始化一些第三方的sdk。
public class MyApplication extends Application { @Override
public void onCreate() { //在所有进程中初始化 .... //仅在主进程中初始化 if (mainProcess) {
...
} //仅在后台进程中初始化 if (bgProcess) {
... }
} }
十五:【强制】子线程中不能更新界面,更新界面必须在主线程中进行,网络操作不能在 主线程中调用。
随记:这个很重要。
十六:【推荐】谨慎使用 Android 的多进程,多进程虽然能够降低主进程的内存压力,但会 遇到很多问题
随记:1) 不能实现完全退出所有 Activity 的功能;
2)首次进入,新启动进程的页面时会有延时现象
3)应用内多线程,Application实例化多次,需要考虑各个模块是否都需要在所有进程中初始化
- 多进程间通过 SharedPreferences 共享数据时不稳定。
十七:【推荐】SharedPreference 提交数据时,尽量使用 Editor#apply(),而非 Editor#commit()。一般来讲,仅当需要确定提交结果,并据此有后续操作时,才使 用 Editor#commit()。
随记:SharedPreference 相关修改使用 apply 方法进行提交会先写入内存,然后异步写入 磁盘,commit 方法是直接写入磁盘。如果频繁操作的话 apply 的性能会优于 commit, apply 会将最后修改内容写入磁盘。但是如果希望立刻获取存储操作的结果,并据此做相应的其他操作,应当使用 commit