美文网首页
Android编程规范(新手必看)

Android编程规范(新手必看)

作者: 裸睡爽翻天 | 来源:发表于2018-02-09 09:31 被阅读0次

可能对于大部分大佬来说,这些可能都是最基本的,但是人脑不是机器,可能每个人都不一样,总会在一些细节上忽略,今天我就大概罗列下平常的一些细节

1.编程指南

1.1文件命名规则

1.2.1类名是用大写字母写的

对于扩展了Android组件的类,类的名称应该以组件的名称结束:例如:SignInActivity、SignInFragment、ImageUploaderService、ChangePasswordDialog。

1.2.2 资源文件

资源文件名使用小写的下划线写的。

1.2.2.1 Drawable文件

关于Drawable的命名规则:

image

关于icon的命名规则:

image

selector选择器的一些命名规则:

image

1.2.2.2 Layout文件

布局文件应该与它们对应的Android组件的名称相匹配,而且布局文件名字要以最后一个组件的名称开头,例如:如果我们为SignInActivity创建一个布局,那么布局文件的名称应该是activity_sign_in.xml。

image

注:有一点不同的是,当我们为listview创建一个Adapter的时候,布局要以item开头。有些情况下这些规则是不可能适用的。例如:当创建布局文件时,这些文件时其他布局的一部分,在这种情况下,应该适用前缀partial_

1.2.2.3 Menu files

与布局文件类似,菜单文件应该与组件名称相匹配。例如:如果我们定义一个将在UserActivity中使用的菜单文件。那么该文件的名称应该是activity_user.xml。

1.2.2.4 Value files

Values文件夹中的资源文件应该是复数,例如:Strings.xml、styles.xml、 colors.xml, dimens.xml, attrs.xml

2 代码的日常规范

2.1 Java 语言规则

2.1.1不要忽视异常

尽可能的不要这样做:

void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
  }
}

虽然您可能认为您的代码永远不会遇到这个错误条件,或者处理它不重要,但忽略上面这样的异常会在代码中创建中埋下坑,可能很多人在刚开始接触Android的时候,都会觉得这样写也挺好呀之类的,但是越到后面你会发现都是坑呀。
我建议可以这样来处理:
1.在调用的时候抛出异常

void setServerPort(String value) throws NumberFormatException {
    serverPort = Integer.parseInt(value);
}

2.捕获之后重新抛出一个新的异常

void setServerPort(String value) throws ConfigurationException {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        throw new ConfigurationException("Port " + value + " is not valid.");
    }
}

2.1.2 不要捕捉通用的异常

最好不要这么做:

try {
    someComplicatedIOFunction();        // may throw IOException
    someComplicatedParsingFunction();   // may throw ParsingException
    someComplicatedSecurityFunction();  // may throw SecurityException
    // phew, made it all the way
} catch (Exception e) {                 // I'll just catch all exceptions
    handleError();                      // with one generic handler!
}

千万不要这样做。几乎所有情况下都不适合捕获常规异常或 Throwable(最好不要捕获 Throwable,因为它包含 Error 异常)。这样做非常危险,因为这意味着系统会在处理应用级错误期间捕获到您从未预料到的异常(包括 ClassCastException 之类的 RuntimeException)。它掩盖了代码的故障处理属性,也就是说,如果有人在您所调用的代码中添加了一种新类型的异常,编译器不会帮助您意识到您需要采取不同的方式来处理该错误。在大多数情况下,您不应以相同的方式处理不同类型的异常。
送大家这么一句话:异常是您的朋友!当编译器抱怨您没有捕获异常时,别闷闷不乐!您应该微笑:因为编译器让您能够更加轻松地捕获代码中的运行时错误。

2.2 Java风格的规范

2.2.1 遵循字段命名规范

非公开且非静态字段的名称以 m 开头。
静态字段的名称以 s 开头。
其他字段以小写字母开头。
公开静态 final 字段(常量)为全部大写并用下划线连接 (ALL_CAPS_WITH_UNDERSCORES)。
例如:

public class MyClass {
    public static final int SOME_CONSTANT = 42;
    public int publicField;
    private static MyClass sSingleton;
    int mPackagePrivate;
    private int mPrivate;
    protected int mProtected;
}

2.2.2将首字母缩写词视为字词

在为变量、方法和类命名时,请将首字母缩写词和缩写形式视为字词,使名称更具可读性:

图片.png

2.2.3 使用空格缩进

我们使用四 (4) 个空格来缩进块,

if (x == 1) {
    x++;
}

我们使用八 (8) 个空格来缩进自动换行,包括函数调用和赋值。正确示例如下:

Instrument i =
        someLongExpression(that, wouldNotFit, on, one, line);

错误示例如下:

Instrument i =
    someLongExpression(that, wouldNotFit, on, one, line);

2.2.4 使用标准大括号样式

左大括号不单独占一行,与其前面的代码位于同一行:

class MyClass {
    int func() {
        if (something) {
            // ...
        } else if (somethingElse) {
            // ...
        } else {
            // ...
        }
    }
}

我们需要在条件语句周围添加大括号。例外情况:如果整个条件语句(条件和主体)适合放在同一行,那么您可以(但不是必须)将其全部放在一行上。例如,我们接受以下样式:

if (condition) {
    body();
}

同样也接受以下样式:

if (condition) body();

但不接受以下样式:

if (condition)
    body();  // bad!

2.2.5 注释

2.2.5.1 注释实践

注释应该位于同一语言元素的其他修饰符之前。简单的标记注释(例如 @Override)可以与语言元素列在同一行。如果有多个注释或参数化注释,则应各占一行并按字母顺序排列。
ava 中 3 个预定义注释的 Android 标准做法如下:

字段

应用于字段的注释应在同一行中列出,除非该行达到最大行长度。

@Nullable @Mock DataManager mDataManager;

2.2.6 限制变量的作用域

尽可能缩小局部变量的作用域。这样做有助于提高代码的可读性和可维护性,并降低出错的可能性。每个变量应该在包含变量所有使用场合的最内层的块中进行声明。

局部变量应该在首次使用时声明。几乎每个局部变量声明都应该包含一个初始化程序。如果您还没有足够的信息来合理地初始化某个变量,请推迟到信息充足时再进行声明。

2.2.7 日志记录

使用Log类提供的日志记录方法可以输出错误消息或其他信息,这些信息可能对开发人员识别问题有用

虽然日志记录非常有必要,但对性能却有明显的负面影响,如果不能保持一定程度的简洁性,就会迅速失去其实用性。日志记录工具提供以下 5 种不同级别的日志记录:

ERROR:在出现极其严重的情况时使用。例如,某些事件会导致用户可见的后果,如果不明确删除某些数据、卸载应用、清除数据分区或重写整个设备(或更糟),则无法恢复。系统一直会记录此级别的日志。一般情况下,最好向统计信息收集服务器报告能够说明
ERROR 级别的一些日志记录情况的问题。

WARNING:在出现比较严重和意外的情况时使用。例如,某些事件会导致用户可见的后果,但是通过执行某些明确的操作(从等待或重启应用,一直到重新下载新版应用或重新启动设备)可在不丢失数据的情况下恢复。系统一直会记录此级别的日志。可以考虑向统计信息收集服务器报告能够说明
WARNING 级别的一些日志记录情况的问题。

INFORMATIVE:用于记录大多数人感兴趣的信息。例如,当检测到某种情况会造成广泛的影响时,尽管不一定是错误,系统也会记录下来。这种情况应该仅由一个被视为该领域最具权威性的模块来记录(避免由非权威组件重复记录)。系统一直会记录此级别的日志。

DEBUG:用于进一步记录设备上发生的可能与调查和调试意外行为相关的情况。您应该只记录收集有关组件的足够信息所需的信息。如果您的调试日志是主要日志,那么您可能应采用 VERBOSE 级别的日志记录。
系统会记录此级别的日志(即使在发布版本中),并且周围要有 if (LOCAL_LOG) 或 if (LOCAL_LOGD) 块,其中 LOCAL_LOG[D] 在您的类或子组件中定义。这样一来,系统有可能停用所有此类日志记录。因此,if (LOCAL_LOG) 块中不得包含有效逻辑。为日志编译的所有字符串也需要放在 if
(LOCAL_LOG) 块中。如果日志记录调用会导致字符串编译在 if (LOCAL_LOG) 块之外发生,则不应将其重构为方法调用。
有些代码仍然在使用 if (localLOGV)。虽然名称并不规范,但也可接受。
VERBOSE:用于记录其他所有信息。系统仅针对调试版本记录此级别的日志,并且周围要有 if (LOCAL_LOGV) 块(或同类块),以便能够默认编译。所有字符串编译都将从发布版本中删除,并且需要在 if (LOCAL_LOGV) 块中显示。

Log.v(String tag, String msg) (verbose)

Log.d(String tag, String msg) (debug)

Log.i(String tag, String msg) (information)

Log.w(String tag, String msg) (warning)

Log.e(String tag, String msg) (error)

作为一般规则,我们使用类名作为标记,并将其定义为文件顶部的静态最终字段。 例如:

public class MyClass {
    private static final String TAG = MyClass.class.getSimpleName();

    public myMethod() {
        Log.e(TAG, "My error message");
    }
}

必须在发布版本上禁用VERBOSE和DEBUG日志。 还建议禁用INFORMATION,WARNING和ERROR日志,但如果您认为可能有助于确定发布版本上的问题,则可能希望保持其启用状态。 如果您决定启用它们,则必须确保它们不泄露私人信息,例如电子邮件地址,用户ID等。
为了方便调试,但同时也为了避免泄露信息,我们可以这样做,仅在调试版本上显示日志:

if (BuildConfig.DEBUG) Log.d(TAG, "The value of x is " + x);

2.2.8 类成员排序

这个并没有硬性的要求,但使用逻辑和一致的顺序将提高代码的可学性和可读性。 建议使用以下命令:
Constants
Fields
Constructors
Override methods and callbacks (public or private)
Public methods
Private methods
Inner classes or interfaces
例如:

public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();

    private String mTitle;
    private TextView mTextViewTitle;

    @Override
    public void onCreate() {
        ...
    }

    public void setTitle(String title) {
        mTitle = title;
    }

    private void setUpView() {
        ...
    }

    static class AnInnerClass {

    }

}

如果您的类正在扩展一个Android组件(例如Activity或Fragment),那么排序重写方法以便它们匹配组件的生命周期是一个好习惯。 例如,如果您有一个实现onCreate(),onDestroy(),onPause()和onResume()的Activity,则正确的顺序是:

public class MainActivity extends Activity {

    //Order matches Activity lifecycle
    @Override
    public void onCreate() {}

    @Override
    public void onResume() {}

    @Override
    public void onPause() {}

    @Override
    public void onDestroy() {}

}

2.2.9 方法中参数的排序

在为Android编程时,定义采用Context的方法是相当常见的。 如果你正在编写这样的方法,那么上下文必须是第一个参数
相反的情况是应该始终是最后一个参数的回调接口。

Examples:
// Context always goes first
public User loadUser(Context context, int userId);

// Callbacks always go last
public void loadUserAsync(Context context, int userId, UserCallback callback);

2.2.10 字符串常量,命名和值

Android SDK的许多元素(如SharedPreferences,Bundle或Intent)都使用键值对方法,所以即使对于一个小应用程序,您最终也不得不编写大量的字符串常量。
当使用这些组件之一时,您必须将这些键定义为一个静态的最终字段,并且按照下面的指示作为前缀。

图片.png

请注意,Fragment - Fragment.getArguments()的参数也是一个Bundle。 但是,因为这是Bundles的一个非常常见的用法,我们为它们定义了一个不同的前缀。
Example:
// 请注意,该字段的值与名称相同以避免重复问题

static final String PREF_EMAIL = "PREF_EMAIL";
static final String BUNDLE_AGE = "BUNDLE_AGE";
static final String ARGUMENT_USER_ID = "ARGUMENT_USER_ID";

// 与意图相关的项目使用完整的包名称作为值

static final String EXTRA_SURNAME = "com.myapp.extras.EXTRA_SURNAME";
static final String ACTION_OPEN_USER = "com.myapp.action.ACTION_OPEN_USER";

2.2.11

当数据通过Intent或Bundle传递给Activity或Fragment时,不同值的键必须遵循上面的规则。
当一个Activity或Fragment需要参数时,它应该提供一个公共的静态方法来帮助创建相关的Intent或Fragment。
我们可以用getStartIntent();来命名

public static Intent getStartIntent(Context context, User user) {
    Intent intent = new Intent(context, ThisActivity.class);
    intent.putParcelableExtra(EXTRA_USER, user);
    return intent;
}

对于Fragment:

public static UserFragment newInstance(User user) {
    UserFragment fragment = new UserFragment();
    Bundle args = new Bundle();
    args.putParcelable(ARGUMENT_USER, user);
    fragment.setArguments(args)
    return fragment;
}

注1:这些方法应该在onCreate()之前的类的顶部。

注2:如果我们提供上述方法,那么额外和参数的密钥应该是私有的,因为不需要在课堂外暴露出来。

2.2.12 每行长度的限制

并没有一个精确的公式来解释如何进行行换行,而且通常不同的解决方案是有效的。然而,有一些规则可以适用于一般情况。
赋值运算符的例外
操作符规则的断点是赋值运算符=,在操作符后面出现换行符。

int longName =
        anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne + theFinalOne;

当多个方法被链接在同一行中——例如,在使用构建器时——对方法的每一个调用都应该在其自己的行中进行,从而打破了前面的行。

Picasso.with(context).load("http://ribot.co.uk/images/sexyjoe.jpg").into(imageView);  //Bad

Picasso.with(context)
        .load("http://ribot.co.uk/images/sexyjoe.jpg")
        .into(imageView);  //Good

长参数的情况下
当一个方法有很多参数或者它的参数很长时,我们应该在每个逗号之后断行,

loadPicture(context, "http://ribot.co.uk/images/sexyjoe.jpg", mImageViewProfilePicture, clickListener, "Title of the picture"); // bad
loadPicture(context,
        "http://ribot.co.uk/images/sexyjoe.jpg",
        mImageViewProfilePicture,
        clickListener,
        "Title of the picture");// Good

2.2.13 RxJava 的链样式

public Observable<Location> syncLocations() {
    return mDatabaseHelper.getAllLocations()
            .concatMap(new Func1<Location, Observable<? extends Location>>() {
                @Override
                 public Observable<? extends Location> call(Location location) {
                     return mRetrofitService.getLocation(location.id);
                 }
            })
            .retry(new Func2<Integer, Throwable, Boolean>() {
                 @Override
                 public Boolean call(Integer numRetries, Throwable throwable) {
                     return throwable instanceof RetrofitError;
                 }
            });
}

2.3 XML的规范

2.3.1 当XML元素没有任何内容时,必须使用自闭标记。

This is good:

<TextView
    android:id="@+id/text_view_profile"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

This is bad :

<!-- Don\'t do this! -->
<TextView
    android:id="@+id/text_view_profile"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >
</TextView>

2.3.2 Resources 命名

2.3.2.1 ID 命名

IDs 应该以小写下划线的元素名称作为前缀。例如:


图片.png
<ImageView
    android:id="@+id/image_profile"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

Menu example:

<menu>
    <item
        android:id="@+id/menu_done"
        android:title="Done" />
</menu>

2.3.2.2 Strings

字符串名称以一个前缀来标识它们所属的部分。例如registration_email_hint或registration_name_hint。如果字符串不属于任何部分,则应遵循以下规则:

图片.png

2.3.2.3 Styles and Themes

与其他资源不同,样式名是用大写字母写的。

总而言之:保持一致。如果您正在修改代码,请花几分钟时间看一下周围的代码并确定其样式。如果该代码在 if 语句周围使用空格,那么您也应该这样做。如果代码备注的周围是用星号组成的小方框,您也应该将备注放在这样的小方框内。

制定样式规范的目的是整理出通用的编码词汇表,以便人们可以专注于您所说的内容,而不是您表达的方式。我们在此提出整体样式规则,让用户都知道这一词汇表,但局部样式也很重要。如果你添加到文件的代码看起来与其周围的现有代码明显不同,那么当你读到此处时,请及时修正吧!

不足的地方,还请批评指正!

相关文章

  • Android编程规范(新手必看)

    可能对于大部分大佬来说,这些可能都是最基本的,但是人脑不是机器,可能每个人都不一样,总会在一些细节上忽略,今天我就...

  • Android 开发规范

    前言 本文参考Google Java编程规范和阿里巴巴Java规范,Android编码规范部分参考Android开...

  • Android 代码命名规范

    前言 根据 Google Java 编程规范 & Google 官方 Android 编码规范,整理一份全面 & ...

  • 【Android 进阶】 代码规范

    前言 这份文档参考了 Google Java 编程风格规范和 Google 官方 Android 编码风格规范。该...

  • Android编程规范

    命名规范 1. 基本原则 (1) 代码风格与android源码保持一致(2) 命名要清晰明了、有明确含义(3) ...

  • Android 编程规范

    架构&分包 -- 原则 包名应让人一目知意:英文命名描述其功能。 分包层次应尽可能的低,减短包名长度。 Model...

  • Android 编程规范

    前言 通过建立代码编写规范,形成Android编码约定,提高程序的可靠性、可读性、可修改性、可维护性、一致性,保证...

  • Android 规范编程

    1.Android 资源文件命名与使用 2.Android 基本组件 2.1 Activity IntentAct...

  • [最新] Android 代码规范大全(Android开发速看)

    编程不规范,亲人两行泪。今天就来分享一下最新的 Android 代码规范大全。原文地址:代码规范大全[https:...

  • iOS开发博客、资料、文档整理

    一、资料 1.iOS禅与 Objective-C 编程艺术 不论你新手还是大牛,搞iOS开发都应必看的文章iOS禅...

网友评论

      本文标题:Android编程规范(新手必看)

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