美文网首页
Android 编码规范

Android 编码规范

作者: Xiho丶 | 来源:发表于2016-03-17 13:23 被阅读159次

    命名基本原则

    • 驼峰式
    • 描述性:有一定的意义,避免难懂的名称
    • 唯一性:同一个类中的字段避免相似同义的字段名
    • 使名称足够长以便有一定的意义

    分类命名规范

    • 包的命名:com.woyou.项目名 具体参考基础框架的结构和命名

    • 类的命名:
      类的名字必须由大写字母开头而单词中的其他字母均为小写;如果类名称由多个单词组成,则每个单词的首字母均应为大写例如TestPage;如 果类名称中包含单词缩写,则这个所写词的每个字母均应大写,如:XMLExample,还有一点命名技巧就是由于类是设计用来代表对象的,所以在 命名类时应尽量选择名词。 例如: Circle

    • 常用类命名规范

    Activity:描述+Act
    Fragment:描述+Frag
    View:描述+View
    Receiver:描述+Receiver
    Service:描述+Service
    请求bean:请求描述+Req
    
    • 字段和函数的命名:
      首字母小写的驼峰式命名,方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头。例如:txtTitle、 sendMessage()

    • 常量的命名
      常量的名字应该都使用大写字母,并且指出该常量完整含义。如果一个常量名称由多个单词组成,则应该用下划线来分割这些单词。例如: MAX_VALUE

    • 参数的命名
      参数的命名规范和方法的命名规范相同,请尽量保证参数的命名尽可能明确。

    • 基本数据类型与常用数据类型命名规范

    Integer:int+描述          Char:chr+描述          Boolean:bln+描述 
    Long:lng+描述           Short:shr +描述         Double:dbl+描述
    String:str+描述           Float:flt+描述          Single:sng+描述
    DataTime:dt+描述         int[](数组):arr+描述        Object:obj+描述     
    List:描述+List
    局部变量:String  srtName;
    全局变量 :  String mStrName; 如果是全局变量就在变量名加上m字母再将第二个单词首字母改为大写。
    
    • 控件命名规范(编码与XML的id)
    TextView 代码:txt+描述 ;XML id:txt_+描述 (下面不再详述) 全局变量:mTxt+描述,局部变量:txt+描述 (全局与局部的区别下面不再详述)
    Button :btn+描述  ;
    ImageButton :ib+描述
    ImageView :img+描述
    CheckBox :chk+描述
    RadioButton :rb+描述
    AnalogClock :ac+描述 
    DigitalClock :dc+描述
    DatePicker :dp+描述
    TimePicker :tp+描述
    ToggleButton :tb+描述
    EditText:edit+描述
    ProgressBar:pb+描述
    SeekBar:sb+描述
    AutoCompleteTextView:autotxt+描述
    MultiAutoCompleteTextView:mlautotxt+描述 
    ZoomControls:zc+描述
    Include:ind+描述 
    VideoView:vv+描述
    WebView:wv+描述
    RatingBar:ratbr+描述
    Tab:tab+描述
    Spinner:spin+描述
    Chronometer:chro+描述
    ScrollView:sv+描述
    TextSwitcher:tswi+描述  
    Gallery:gal+描述
    ImageSwitcher:imgswi+描述
    GridView:gv+描述
    ListView:lv+描述
    ExpandableList: exl+描述
    MapView: mv+描述
    
    • 其他变量命名规范
      变量命名:前缀+类型描述+意义描述
      例如:全局变量 mSelectorOnItemTouch或者局部变量 selectorOnItemTouch

    注释

    • 文件注释(记录每次的修改人、时间和内容)
    /* 
     * @Title:  ${file_name} 
     * @author:  tomcat
     * @data:  ${date} ${time} <创建时间>
     * 
     * @history:<以下是历史记录>
     *
     * @modifier: <修改人>
     * @modify date: ${date} ${time} <修改时间>
     * @log: <修改内容>
     *
     * @modifier: <修改人>
     * @modify date: ${date} ${time} <修改时间>
     * @log: <修改内容>
     */
    
    • 类注释
    /** 
     * ${todo}<请描述这个类是干什么的> 
     * @author  tomcat 
     * @versionCode 1 <每次修改提交前+1>
     */
    
    • 函数(方法)注释
    /**  
     * public函数
     * ${todo}<请描述这个方法是干什么的> 
     * @param pos <参数说明>
     * @throw 
     * @return ${return_type} <返回值说明>
     */
    public Object getItemByPos(int pos){
         .......
    }
    
    //<请描述这个方法是干什么的> 
    private void create(){
        // 在函数中也可适当添加注释
    }
    
    • 成员变量注释
    private Context mContext; //上下文对象
    private TextView txtTitle;   //标题
    private int lastTouchX;      //最后手指按下时的X轴坐标
    
    • 局部变量注释
    局部变量和逻辑块也要适当加上// 注释
    public InputStream open(){
        String webUrl = "www.baidu.com"; //要连接的网址
        ......
        ......
    }
    
    • 每一个类、字段与函数必须有注释,注释行数不少于代码行数的五分之一(提醒作用 不强制)

    编码规范

    1 明确方法功能,精确实现方法设计,一个函数仅完成一个功能。
    2 函数的调用者应该负责对参数的合法性检查,参数的合法性检查尽量不要放在函数中实现(视情况而定)

    public Goods getGoodsByName(String name){
        if( TextUtils.isEmpty(name) ){
             return null;
        }
        ......
        ......
    }
    {
        Goods goods = getGoodsByName(name);
        if( goods == null ){
            return;
        }
        ......
        ......
    }
    X
    
    {
        if( TextUtils.isEmpty(name) ){
             return;
        }
        Goods goods = getGoodsByName(name);
        ......
        ......
    }
    √
    

    3 明确类的功能,精确(而非近似)地实现类的设计。一个类仅实现一组相近的功能。

    划分类的时候,应该尽量把逻辑处理、数据和显示分类,实现类功能的单一性
    比如:
    数据类不能包含数据处理的逻辑,比如Bean实体
    通信类不能包含显示处理的逻辑,比如Socket、DownloadManger
    

    4 所有数据类必须重载toString()方法, 返回该类有意义的内容。

    public TopoNode{
        private String nodeName;
        
        public String toString(){
            return  "NodeName : " + nodeName;
        }
    }
    

    5 数据库、IO操作等使用后需要close()的对象必须在try-catch-finally的finally中close().

    try  
    {  
          //   . . .   . . .  
    }  
    catch(IOException  ioe)  
    {  
          // . . .   . . .  
    }  
    finally  
    {  
            try  
            {  
                 out.close( ) ;  
            }  
            catch(IOException  ioe)  
            {  
                 // . . .   . . .  
            }  
    }
    

    6 避免使用不易理解的数字,用有意义的标识来替代。涉及物理状态或者有意义的数字,必须用有意思的静态常量来代替。所有switch case 的int值包括message的what值都必须有常量来描述并加上注释。
    可读性差的代码:

    switch (code) {
        case 1:
        ... ...
        break;
    X
    
    private final static int IDLE = 1; //空闲状态
    switch (code) {
        case IDLE:
        ... ...
        break;
    √
    

    7 View的显示控制逻辑最好放在Controller中(使用MVC时)

    8 Activity与Fragment中的代码不允许超过400行,最好控制在300行以内,超过400行代码的Activity意味着你的代码可能没有做任何封装和划分,是时候优化你的代码了。

    9 所有超过20行的抽象实现类(或者匿名内部类)都必须抽出来单独实现再实例化,禁止运行时实现, 与执行过程无关的代码尽量不要放在执行过程中

    重构前:
    {
            testTimerTask=new TimerTask() {
                
                @Override
                public void run() {
                    runOnUI(new Runnable() {
                        public void run() {
    
                            List<Integer> netData=NetworkStrengthController.getInstance(mContext).getNetData();
                            if(!netData.isEmpty()){
                                strength_now.setText("当前信号强度:"+netData.get(netData.size()-1)+"dB");
                                strength_max.setText("信号强度最高:"+Collections.max(netData)+"dB");
                                strength_low.setText("信号强度最低:"+Collections.min(netData)+"dB");
                                if(netStates.size()>0){
                                    strength_base.setText("连接基站个数:"+netStates.size());
                                }
                                
                                //评级
                                if(netStates.size()>3){
                                    strength_rate_iv.setImageResource(R.raw.netstrength_poor);
                                }else{
                                    float sum=0;
                                    for(float num: netData){
                                        sum=sum+num;
                                    }
                                    float avg=sum/netData.size();
                                    if(avg>-60){
                                        strength_rate_iv.setImageResource(R.raw.netstrength_good);
                                    }else if(avg>-90){
                                        strength_rate_iv.setImageResource(R.raw.netstrength_normal);
                                    }else if(avg>-110){
                                        strength_rate_iv.setImageResource(R.raw.netstrength_poor2);
                                    }else{
                                        strength_rate_iv.setImageResource(R.raw.netstrength_poor);
                                    }
                                }
                            }
                        
                        }
                    });
                }
            };
                    testTimer.schedule(testTimerTask, 0, 1000);
    }
    XXX
    
    重构后:
    public class NetworkController{
         //注释
        public setStrengthNow(TextView tv){
            int now = getStrengthNow();
             tv.setText("当前信号强度:"+ now +"dB");
        }
        //注释
        public setStrengthMax(TextView tv){
            int max = getStrengthMax();
            tv.setText("信号强度最高:"+ max +"dB");
        }
        //注释
        public setStrengthLow(TextView tv){
            int low = getStrengthLow();
            tv.setText("信号强度最低:"+ low +"dB");
        }
        //显示信号强度评级
        public void setStrengthRate(ImageView iv){
            ... ... //计算评级
            ... ...//设置显示
        }
    }
    Activity代码:
    Runnable runTest = new Runnable(){
         public void run() {
               boolean hasSignal = mNetworkController.hasSignal(); //是否检测到信号
               if(hasSignal){
                    //显示信号强度
                    mNetworkController.setStrengthNow(txtStrengthNow);
                    mNetworkController.setStrengthMax(txtStrengthMax);
                    mNetworkController.setStrengthLow(txtStrengthLow);
                    .....
                    //显示评级
                    mNetworkController.setStrengthRate(ivStrengthRrate);
                    
               }
         }
    }
    {
        testTimerTask=new TimerTask() {
                
        @Override
        public void run() {
            runOnUI(runTest);
        }
        };
        testTimer.schedule(testTimerTask, 0, 1000);
    }
    √√√
    

    11 Activity与Service之间的通信只能使用广播或者Binder代理对象

    12 ListView的Adapter的getView函数代码统一使用自定义View来封装(也就是每一种Item都是一类自定义View)

    13 所有相似的Dialog弹出框逻辑都抽取到Utils中便于复用。

    14 禁止直接new Thread()必须使用线程池启动线程。

    15 逻辑复杂的一块UI应封装为自定义View,良好的Activity结构应该由多个自定义View组成,以减少Activity中的代码

    16 布局能用一层就用一层尽量减少布局嵌套

    17 注释的代码能删除就删除不要留着。

    18 UI模块较多的项目,Activity应该按模块分包

    19 函数的实现横不可超过半屏幕竖不可超过一屏 超过了就要按逻辑块抽出别的子函数。

    20 用不到的第三方库就删掉

    21 禁止使用静态变量在activity和activity之间、activity和service之间共享数据

    22 Activity中在一个View.OnClickListener中处理所有的逻辑

    23 不要重用父类的handler,对应一个类的handler也不应该让其子类用到,否则会导致message.what冲突

    24 如果多个Activity中包含共同的UI处理,那么可以提炼一个父Activity,把通用部分封装起来由它来处理,其他activity只要继承它即可

    25 屏幕适配:使用适配方案的值写死所有控件的尺寸

    26 view与view之间不要直接通信 应该通过activity来转接

    27 不要使用Log.i() Log.d() 进行日志打印,应该使用一个包含统一开关的测试类进行统一打印。比如封装一个LogUtils。

    28 异常捕获不要直接catch(Exception ex),应该把异常细分处理

    29 如果多段代码重复做同一件事情,说明此段代码各语句之间有实质性关联并且是完成同一件事,那么可以把此段代码构造成一个 新的函数。

    30 不要使用难懂的技巧性很高的语句,除非很有必要时。

    相关文章

      网友评论

          本文标题:Android 编码规范

          本文链接:https://www.haomeiwen.com/subject/uerclttx.html