4.2 Android 编码规范
前面写的内容就是为了编码规范做铺垫。
图4-3 分门别类存放各种类
有人说,编码规范网上多的是,我就见过有人网上摘抄了一些然后跟我讲这是他们团队的编码规范的。这不对,不能为了规范而规范,规范是为了解决实际问题的。我个人经过血和泪的后的经验总结如下:
1)要分门别类存放各种类,如图4-3所示。
2)要怎么使用findViewById语句?
看过项目中很多人都这么使用findViewById语句:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((TextView)findViewById(R.id.login_status_message)) .setVisibility(View.VISIBLE); }
从面向对象的角度出发,以下写法是不是更好呢:
TextView tvLoginStatusMessage; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvLoginStatusMessage = (TextView)findViewById(R.id.login_status_message); tvLoginStatusMessage.setVisibility(View.VISIBLE); }
我们观察到,把控件对象声明在Activity级别会更好一些,在initViews中对其赋值,而在Activity的其他地方还有使用的机会。
也许有人会质疑,如果这个控件只使用了一次,那么第一种写法其实是最好的。但这毕竟是少数,我们现在要统一编码规范,只能牺牲一部分人的利益,来达到协同工作的效率最大化。
3)Layout中的常量,要在资源strings.xml中定义。
以下的使用方式是错误的:
<TextView android:text="评论 " …… ../>
我们要将“评论”这个常量定义在strings.xml中:
<resources> <string name="tvPersonCenter">评论 </string> </resources>
然后在Layout布局文件中这样使用:
<TextView android:text="@string/tvPersonCenter" …… ../>
另一方面,在Activity中也需要设置一些常量,不能把它写死,要将其定义在strings.xml中,然后每次都从资源文件中取值,如下所示:
String loadingMessage = this.getString(R.string.loadingmessage);
Eclipse编译时会检查上述问题,显示在Warnings列表中,开发人员要定期修复Warning中类似的问题。
4)Layout中所有控件的字体大小,都定义在dimens.xml中,它相当于网站的CSS样式表,如下所示:
<?xml version="1.0" encoding="utf-8"?> <resources> <!— 字体定义 — > <dimen name="font_size_tiny">10sp</dimen> <dimen name="font_size_small">12sp</dimen> <dimen name="font_size_normal">14sp</dimen> <dimen name="font_size_normal_high">16sp</dimen> <dimen name="font_size_large">18sp</dimen> <dimen name="font_size_large_high">20sp</dimen> <dimen name="font_size_xlarge">22sp</dimen> <!— 边距 — > <dimen name="offset_2dp">2dp</dimen> <dimen name="offset_4dp">4dp</dimen> <dimen name="offset_6dp">6dp</dimen>
使用方式如下:
<TextView android:textSize= "@dimen/font_size_normal" …… />
此外,对于所有控件的Margin偏移量,我们也需要统一规格,正如上面的dimens.xml中的定义,有若干种尺寸事先定义好供我们选择。
<LnearLayout android:layout_marginLeft= "@dimen/offset_2dp" android:layout_marginRight= "@dimen/offset_4dp"
这样做的好处是,只要稍微修改一下dimens.xml中的定义,就可以批量修改页面的样式。Android的手机千奇百怪,各种分辨率都存在,在一些特殊机型上,font_size_normal字体可能会过大或者过小,我们将其修改为13sp或15sp,就可以迅速看到修改是否符合我们的审美观了。
做得更彻底些,是使用style来统一控件的风格。如果有必要,请使用之。
5)在Acitivity中,定义新的生命周期,从而将onCreate方法拆分为以下3部分:
·initVariables:初始化变量(包括Intent上的数据和Activity内部使用的变量)。
·initViews:加载layout布局文件,初始化控件。
·loadData:调用MobileAPI。
拆分onCreate方法是设计模式中单一职责原则的体现。
6)坚持使用fastJSON自定义实体来作为MobileAPI的数据载体。
像JSONObject、JSONArray、HashMap<String,Object>、ArrayList<String,Object>这些不能序列化的实体,都禁止使用。除非它们仅仅是为了实现某个算法,在方法内部临时使用。
千万别偷懒哦。如果觉得自定义实体很麻烦,建议使用我在第1章1.4节介绍的那个实体自动化生成工具EntityGenerator。
7)页面之间传值,坚持使用Intent携带序列化实体数据的方式。禁止为了省事使用全局变量进行传值的方式。
8)为控件添加事件。以按钮为例,为按钮添加点击事件,统一使用以下这种方式:
btnLogin = (Button)findViewById(R.id.sign_in_button); btnLogin.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { login(); } });
严禁在Layout的控件声明中直接声明事件方法,以下代码是不允许的:
<Button android:onClick="gotoLogin" …… />
9)Activity中不要嵌套内部类,尽量都独立出来,该放哪儿就放哪儿。
10)Adapter的编码规范如下:
·所有Adapter,都放在adapter这个包中。
·Adapter绑定的数据,一律为ArrayList<自定义可序列化实体>。
·在Adapter中创建适合于列表自身的ViewHolder实体类。请统一命名为ViewHolder。
11)实体不要在不同模块间共享,但是可以在同一模块下的不同页面间共享。比如说,不要在美食模块和酒店模块共用同一个实体,但是在美食模块的列表页和详情页,可以共用同一个实体。
12)为节省内存,请使用ArrayList<自定义实体>,而不是HashMap。
ArrayList虽然慢一点,每次查找一个元素,都是o(n),而HashMap则是o(1),但是ArrayList在内存的使用上要少于HashMap。对于Android手机,尤其是配置很低的手机,我们开发App的策略是尽量不占用太多内存,所以请优先选择ArrayList<自定义实体>。
13)图片的处理,请统一使用第三方组件ImageLoader或Fresco来进行异步加载。
14)什么时候使用SharedPreferences?对于简单的配置信息,设置页面的各种开关,这些都是要保存在SharedPreferences中的。对于复杂的对象,比如说User类,比如说城市基础数据,这些数据还是要存储到本地文件中。
15)尽量使用ApplicationContext代替Context,否则会引起内存泄漏。当然,也不是任何地方ApplicationContext都可以代替Context,请参见第6章,将详细介绍因为使用不当而导致的崩溃。
16)数据类型转换一定要进行校验。请使用第1章1.6节介绍的类型安全转换函数,这些函数能帮你做两件事,一是转换失败会有默认值;二是由try…catch…保护,不会轻易抛出空指针或者类型转换失败的崩溃。
17)使用常量来代替枚举。众所周知,枚举的每个值只能是一个整数,而没有toString这样的方法,所以不如在类中定义一个字符串常量方便。此外,有人说枚举的内存开销要比常量大,但我觉得这不是判断常量比枚举好的理由。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论