程序员人生 网站导航

Android开发基础规范(二)

栏目:综合技术时间:2016-11-03 08:12:29

转载请把头部出处链接和尾部2维码1起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52614696

前言:Android中1些开发规范,避免给自己和他人少留坑。

2、代码相干

2.2.15 Field Ordering 属性排序
在类文件顶部声明的任何属性都应当按以下的排序规则进行排序:

  • 1.Enums (枚举类型)
  • 2.Constants (常量)
  • 3.Dagger Injected fields (Dagger注入的属性)
  • 4.Butterknife View Bindings (Butterknife绑定的view)
  • 5.private global variables (private成员变量)
  • 6.public global variables (public成员变量)
    例如:
//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin public static enum { ENUM_ONE, ENUM_TWO } public static final String KEY_NAME = "KEY_NAME"; public static final int COUNT_USER = 0; @Inject SomeAdapter mSomeAdapter; @BindView(R.id.text_name) TextView mNameText; @BindView(R.id.image_photo) ImageView mPhotoImage; private int mUserCount; private String mErrorMessage; public int mSomeCount; public String mSomeString;

使用上述的排序规则有助于保持字段声明的分组,从而增加字段的可读性

2.2.16 Class member ordering 类成员排序

为了提高代码的可读性,组织类成员在1个符合逻辑的方式中是非常的重要,请按以下的排序方式去实现:

  • 1.Constants
  • 2.Fields
  • 3.Constructors
  • 4.Override methods and callbacks (public or private)
  • 5.Public methods
  • 6.Private methods
  • 7.Inner classes or interfaces

例如:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin public class MainActivity extends Activity { private int mStepCount; public static newInstance() { } @Override public void onCreate() { } public void setColor(Color color) { } private int getId() { } static class AnInnerClass { } interface SomeInterface { } }

在Android框架中任何生命周期的方法应当在其相应的生命周期中排序,例如:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin public class MainActivity extends Activity { // Field and constructors @Override public void onCreate() { } @Override public void onStart() { } @Override public void onResume() { } @Override public void onPause() { } @Override public void onStop() { } @Override public void onRestart() { } @Override public void onDestroy() { } // public methods, private methods, inner classes and interfaces }

2.2.17 Method parameter ordering 方法的参数排序
当定义方法时,参数应当依照以下的规则排序:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin public Post loadPost(Context context, int postId); public void loadPost(Context context, int postId, Callback callback);

Context上下文参数应放在第1位,并且Callback回调参数放置在最后

2.2.18 String constants, naming, and values 字符串常量、命名和值
当使用字符串常量时,其应当修饰为静态final并且遵守以下规则:

2.2.19 Enums 枚举
枚举的使用仅仅在实际需要用到时。如果另外1种方法可行,此时应当选择更好的方式去实现它,例如:
相对下面这样:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin public enum SomeEnum { ONE, TWO, THREE }

更推荐这样做:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin private static final int VALUE_ONE = 1; private static final int VALUE_TWO = 2; private static final int VALUE_THREE = 3;

2.2.20 Arguments in fragments and activities

在fragment和activity中的参数
当我们使用Intent或Bundle传递数据时,值的键必须使用下面定义的约定:

  • Activity
    • 传递数据到1个activity必须使用1个KEY的援用,像下面这样定义:
      private static final String KEY_NAME = “com.package.name.activity.KEY_NAME”;
  • Fragment
    • 传递数据到1个fragment必须使用1个EXTRA的援用,像下面这样定义:
      private static final String EXTRA_NAME = “EXTRA_NAME”;

当创建fragment或activity的新实例触及到传递数据时,我们应当提供1个静态的方法来获得新的实例,传递的数据作为参数。例如:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin //Activity中 public static Intent getStartIntent(Context context, Post post) { Intent intent = new Intent(context, CurrentActivity.class); intent.putParcelableExtra(EXTRA_POST, post); return intent; } //Fragment中 public static PostFragment newInstance(Post post) { PostFragment fragment = new PostFragment(); Bundle args = new Bundle(); args.putParcelable(ARGUMENT_POST, post); fragment.setArguments(args) return fragment; }

2.2.21 Line Length Limit 行长度限制
代码的行数字符长度最好不要超过100个字符,这样代码的可读性会更高。有时为了实现上述要求,我们需要做的:

  • 1.提取数据到1个局部变量
  • 2.提取代码逻辑到外部的方法
  • 3.将1段较长的代码换行显示
  • 注意:对代码的注释和导入声明,超过100个字符的限制是可以的。

2.2.21.1 Line-wrapping techniques 换行技能
当触及到换行时,有1些情况我们应当保持与格式化代码的1致性。

  • 运算符换行
    当我们需要在1个运算公式换行时,需要在运算符前面换行:
//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin int count = countOne + countTwo - countThree + countFour * countFive - countSix + countOnANewLineBecauseItsTooLong;

如果需要,你可以直接在“=”后换行:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin int count = countOne + countTwo - countThree + countFour * countFive + countSix;
  • 方法链
    当触及到方法链时(这个比较流行,建议写方法链,RxJava几近都是),每一个方法的调用都应当另起1行:
    不要下面这样:
//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin Picasso.with(context).load("someUrl").into(imageView); 取而代之应这样: Picasso.with(context) .load("someUrl") .into(imageView);
  • 长参数
    对1个含有长参数的方法,我们在适当的情况下应当换行。例如当声明1个方法时我们应当在最后1个参数的逗号处换行:
//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin private void someMethod(Context context, String someLongStringName, String text,long thisIsALong, String anotherString) { }

当调用这个方法时,我们应当在每一个参数的逗号后面换行:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin someMethod(context, "thisIsSomeLongTextItsQuiteLongIsntIt", "someText", 01223892365463456, "thisIsSomeLongTextItsQuiteLongIsntIt");

2.2.22 Method spacing(方法间间距)
在同1个类中,方法与方法之间只需要留有1行的空白,以下:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin public String getUserName() { // Code } public void setUserName(String name) { // Code } public boolean isUserSignedIn() { // Code }

2.2.23 Comments(注释)

  • 2.2.23.1 Inline comments(行内注释)
    必要的时候,写注释,其他情况下最好不要写注释,从方法名或成员变量上就可以看出做甚么。

  • 2.2.23.2 JavaDoc Style Comments(java文档的注释风格)
    方法的名字应当起的和该方法的功能相对应,有时可以提供JavaDoc风格的注释。方法名起的好会帮助读者更好的理解方法的功能,同时也会让使用者明白传入方法中参数的作用。

/** * Authenticates the user against the API given a User id. * If successful, this returns a success result * * @param userId The user id of the user that is to be authenticated. */ public class XXX { }
  • 2.2.23.3 Class comments(类注释)
    在创建类注释时,它们应当是成心义的,有描写性的,必要的时候使用超链接。以下:
/** * RecyclerView adapter to display a list of {@link Post}. * Currently used with {@link PostRecycler} to show the list of Post items. */ public class RecyclerView { }

不要写初创作者信息,由于以后会有很多人在这个类上改来改去,写上作者信息是没有任何意义的。

/** * Created By yuiop 22/09/2016 */ public class XXX { }

2.2.24 Sectioning code(分段代码)
2.2.24.1 Java code(java代码)
如果对代码做了“分段”,应当使用下面的方法完成,以下:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin public void method() { } public void someOtherMethod() { } /********* MVP Method Implementations ********/ public void anotherMethod() { } /********* Helper Methods ********/ public void someMethod() { }

不能像下面这样:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin public void method() { } public void someOtherMethod() { } // Mvp Method Implementations public void anotherMethod() { }

这样会更容易定位类中方法。

2.2.24.2 Strings file(字符串文件)
字符串资源文件string.xml中分段注释以下:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin // User Profile Activity <string name="button_save">Save</string> <string name="button_cancel">Cancel</string> // Settings Activity <string name="message_instructions">...</string>

这样写不但可让string文件看起来整洁,还能在需要更改它们时更容易找到。

2.2.24.3 RxJava chaining(RxJava链接)
当进行异步操作时,每步操作都应当在遇到“.”号之前另起1行,以下:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin return dataManager.getPost() .concatMap(new Func1<Post, Observable<? extends Post>>() { @Override public Observable<? extends Post> call(Post post) { return mRetrofitService.getPost(post.id); } }) .retry(new Func2<Integer, Throwable, Boolean>() { @Override public Boolean call(Integer numRetries, Throwable throwable) { return throwable instanceof RetrofitError; } });

这样会使读者更容易理解接下来的异步操作。
2.2.25 Butterknife(Butterknife)
2.2.25.1 Event listeners(事件监听者)
如有可能,尽可能使用ButterKnife绑定监听。举个栗子,可以用ButterKnife替换传统的点击事件:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin mSubmitButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Some code here... } };

换成以下:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin @OnClick(R.id.button_submit) public void onSubmitButtonClick() { }

2.3 XML Style Rules(XML文件中样式规则)
2.3.1 Use self=-closing tags(使用单标记)
在xml布局中,如果1个viwe没有任何子view,那末就应当使用单标记。
用这个:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin <ImageView android:id="@+id/image_user" android:layout_width="90dp" android:layout_height="90dp" />

不用这个:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin <ImageView android:id="@+id/image_user" android:layout_width="90dp" android:layout_height="90dp"> </ImageView>

2.3.2 Resource naming(资源命名)
所有的资源命名规则都应当是小写和下划线的组合,以下:
2.3.2.1 ID naming(id命名)
所有的id命名规则都应当用元素作为前缀。

Element Prefix
ImageView image_
Fragment fragment_
RelativeLayout layout_
Button button_
TextView text_
View view_

例如:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin <TextView android:id="@+id/text_username" android:layout_width="wrap_content" android:layout_height="wrap_content" />

注意:如果1个布局中1种类型的view只有1种,比方toolbar,那末可以直接起名叫toolbar

2.3.2.2 Strings(字符串)
所有的字符串名字应当以该利用确当前功能页面作为前缀,以下:

Screen String ResourceName
Registration Fragment “Register now” registration_register_now
Sign Up Activity “Cancel” sign_up_cancel
Rate App Dialog “No thanks” rate_app_no_thanks

如果没法像上面1样命名,我们可以用下面的方法:

Prefix Description
error_ Used for error messages
title_ Used for dialog titles
action_ Used for option menu actions
msg_ Used for generic message such as in a dialog
label_ Used for activity labels

需要注意以下两点:

  • 1、同1个的字符串资源不能在多个文件中同享使用。如果其中的1个页面字符串产生改变也会造成另外一个页面的改变从而产生问题。每一个页面使用单独的字符串资源会给将来省去很多麻烦。
  • 2、字符串资源必须放在字符串资源文件中,不能写在布局或类中。

2.3.2.3 Styles and themes
当定义style和theme时,每一个单词应当大写开头。以下:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin AppTheme.DarkBackground.NoActionBar AppTheme.LightBackground.TransparentStatusBar ProfileButtonStyle TitleTextStyle

2.3.3 Attributes ordering(属性排序)
定义属性不能只为了看起来整洁,同时能够在布局中快速找到属性位置。以下是基本规则:

  • 1、viwe的id
  • 2、style
  • 3、布局的宽高
  • 4、其他的布局属性,依照字母顺序排序
  • 5、其他的属性,依照字母顺序排序

以下:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin <Button android:id="@id/button_accept" style="@style/ButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentStart="true" android:padding="16dp" android:text="@string/button_skip_sign_in" android:textColor="@color/bluish_gray" />

注意:在Android studio中快速格式化快捷键是:cmd + shift + L
这样做,当布局文件产生变化时,可以通过xml属性快速定位。

本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52614696

2.4 Tests style rules(测试风格规则)
2.4.1 Unit tests(单元测试)
所有测试类起名字都应当和他们被测试的类相对应,并且以Test作为后缀,以下:

Class Test Class
DataManager DataManagerTest
UserProfilePresenter UserProfilePresenterTest
PreferencesHelper PreferencesHelperTest

所有的测试方法应当用@Test进行注释,测试方法应当用下面的模板:

@Test public void methodNamePreconditionExpectedResult() { }

举例,如果我们想测试1个使用不正确邮箱登录的功能,测试方法应当使用以下的:

@Test public void signUpWithInvalidEmailFails() { }

测试应当将重点放在测试方法赋予的功能名称上面,如果在你的测试方法中还有别的情况需要斟酌,这些额外的需要测试的情况应当分到它专门的测试方法中。
如果1个类中包括许多不同的方法,测试应当在多个测试类中进行拆分-这样有助于测试更容易于保护和定位。例如,1个数据库工具类有时候会分解成以下几个测试类:

DatabaseHelperUserTest DatabaseHelperPostsTest DatabaseHelperDraftsTest

2.4.2 Espresso tests(功能测试框架Espresso)
每一个Espresso测试类1般都对应1个Activity,所以命名时应当和对应的Activity相1致,其次是测试,以下:

Class Test Class
MainActivity MainActivityTest
ProfileActivity ProfileActivityTest
DraftsActivity DraftsActivityTest

当使用Espresso API的时候,方法应当换行从而可让声明更容易读,举例以下:

onView(withId(R.id.text_title)) .perform(scrollTo()) .check(matches(isDisplayed()))

这类风格的链接调用不但可让我们每行不超过100个字符,同时也能够让Espresso测试中的链接更加易读。

Gradle Style(Gradle风格)

3.1 Dependencies(依赖)

3.1.1 Versioning
如果1个版本号在多个依赖中多被使用,那末应当在依赖的范围内定义成1个变量,以下:

//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin final SUPPORT_LIBRARY_VERSION = '23.4.0' compile "com.android.support:support-v4:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:recyclerview-v7:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:support-annotations:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:design:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:percent:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:customtabs:$SUPPORT_LIBRARY_VERSION"

将来如果需要更新依赖,那末只需要更新版本号的变量就能够很轻松的控制所有依赖的版本号。

3.1.2 Grouping(分组)

  • 依赖应当以包名来分组,各个组之间应当有1定的间隙,以下:
//create by 逆流的鱼yuiop on 2016/9/22 //blog地址:http://blog.csdn.net/hejjunlin compile "com.android.support:percent:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:customtabs:$SUPPORT_LIBRARY_VERSION" compile 'io.reactivex:rxandroid:1.2.0' compile 'io.reactivex:rxjava:1.1.5' compile 'com.jakewharton:butterknife:7.0.1' compile 'com.jakewharton.timber:timber:4.1.2' compile 'com.github.bumptech.glide:glide:3.7.0'

Compile、testCompile、androidTestCompile依赖一样应当分组到相对应的组别中,以下:

// App Dependencies compile "com.android.support:support-v4:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:recyclerview-v7:$SUPPORT_LIBRARY_VERSION" // Instrumentation test dependencies androidTestCompile "com.android.support:support-annotations:$SUPPORT_LIBRARY_VERSION" // Unit tests dependencies testCompile 'org.robolectric:robolectric:3.0'

这两种方法都可以很容易的找到特定的依赖关系,需要时,它保证依赖的声明既干净又整洁。

3.1.3 Independent Dependencies(独立的依赖关系)

  • 依赖只能利用在利用或目的测试中,确保使用compile,testCompile,androidTestCompile来编译它们。例如,robolectric依赖只能被用来做单元测试,它应当以下:
testCompile 'org.robolectric:robolectric:3.0'

第1时间取得博客更新提示,和更多android干货,源码分析,欢迎关注我的微信公众号,扫1扫下方2维码或长按辨认2维码,便可关注。

这里写图片描述

如果你觉得好,随手点赞,也是对笔者的肯定,也能够分享此公众号给你更多的人,原创不容易

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐