Skip to content
halzhang edited this page Apr 14, 2013 · 1 revision

StartupNews编码规范

说明:欢饮加入StartupNews开发,所有Pull Request需要遵守此代码规范。以下规范只是自己的一些总结,当中可能存在有不合理的地方,如果你有更好的建议,欢迎提出指正。

版本变更记录
时间 作者 版本 变更信息
2010-9-13 张汉国 0.1 初始化
# 一、命名规则 ## 1、图片命名 **命名规则**:类别_描述(_状态).png

例如:

  • ic_mentions_home_default.png 默认状态
  • ic_mentions_home_pressed.png 被按下状态
  • ic_mentions_home_selected.png 被选中状态(聚焦状态)

以上分别是控件处于三个不同状态下的图标。

  • ic:类型,表示图标;
  • mentions_home:描述,表示home这个layout中mentions这个可触发控件;
  • default/pressed/selected:状态,表是控件不同状态

在开发过程中尽量使用xml去描述按钮等控件的在各种状态下的图标显示方式,避免用硬编码的方式。

Xml使用方式如下:

ic_mentions_home.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
	<item android:state_pressed="true"
		android:drawable="@drawable/ic_mentions_home_pressed" />
	<item android:state_focused="true"
		android:drawable="@drawable/ic_mentions_home_selected" />
	<item
		android:drawable="@drawable/ic_mentions_home_default" />
</selector>

在同一个layout下的图标尽量使用相同的描述或者描述前缀,描述的命名与layout的命名需要有一定的关联。

2、layout命名

命名规则:描述_功能.xml

例如:

  • login.xml
  • message_list.xml
  • message_list_item.xml

3、id命名

命名规则:layout描述_view类型缩写_描述

Id命名以图片的命名比较相似,参考例子:

<FrameLayout
	android:id="@+id/header"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:layout_marginTop="10dip">

	<ViewStub
		android:id="@+id/header_small"
		android:inflatedId="@+id/header_small"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:layout="@layout/quickcontact_header_small" />

	<ViewStub
		android:id="@+id/header_medium"
		android:inflatedId="@+id/header_medium"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:layout="@layout/quickcontact_header_med" />

	<ViewStub
		android:id="@+id/header_large"
		android:inflatedId="@+id/header_large"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:layout="@layout/quickcontact_header_large" />

</FrameLayout>

4、Activity,Service类命名

命名规则

  • 描述+Activity.java
  • 描述+Service.java

5、局部变量命名

局部变量命名在最前面 + “t”

二、代码注释

  • 1、公共变量必须注释;
  • 2、每个对外提供调用的方法都必须要有详细的注释;
  • 3、接口需要又更加详细的注释;

三、XML编写格式(layout)

格式要求:

  • 1、 控件开始标签独立一行;
  • 2、 每个属性独立一行,需要缩进,每个属性需要对齐,第一个属性为ID属性;
  • 3、 如果没有子节点,该节点的结束标签与最后一个属性同行。

如下:

<ImageButton 
	android:id="@+id/menu_icon"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:background="@drawable/menuicon" />

代码示例:

<LinearLayout 
	android:id="@+id/menubarlayout"
	android:layout_alignParentBottom="true"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:orientation="horizontal">
	<ImageButton 
		android:id="@+id/playscreen_icon"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:background="@drawable/playscreen" />
	<ImageButton 
		android:id="@+id/listscreen_icon"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:background="@drawable/listscreen" />
	<ImageButton 
		android:id="@+id/onlinescreen_icon"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:background="@drawable/onlinescreen" />
	<ImageButton 
		android:id="@+id/menu_icon"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:background="@drawable/menuicon" />
</LinearLayout>

四、优化

1、UI优化

背景图等“单一”的图片使用draw9patch.bat工具,这样做有两点好处;

  • 可以缩小图片的体积;
  • 可以自适应屏幕拉伸

2、onTouch方法处理:

使用id + switch …… case 的方式,不使用v + if……else(注释部分)。Id为int,v式对象,前者的比较效率高于后者,switch……case的效率也高于if……else

@Override
public boolean onTouch(View v, MotionEvent event) {
	final int action = event.getAction();
	final int id = v.getId();
	switch (action) {
		case MotionEvent.ACTION_UP:
			switch (id) {
				case R.id.playbutton:
					int playerState = controllor.playOrPause();
					updatePlayButtonState(playerState);
					return true;
				case R.id.nextbutton:
					nextButton.setBackgroundResource(R.drawable.nextbutton);
					if (executedLongPressed) {
						executedLongPressed = false;
					} else {
						controllor.next();
					}
					return true;
				case R.id.previousbutton:
					previousButton.setBackgroundResource(R.drawable.previousbutton);
					if (executedLongPressed) {
						executedLongPressed = false;
					} else {
						controllor.previous();
					}
					return true;
				case R.id.playscreen_icon:
					setSelectedTab(TAB_PLAY_SCREEN);
					return true;
				case R.id.listscreen_icon:
					setSelectedTab(TAB_LIST_SCREEN);
					return true;
				case R.id.onlinescreen_icon:
					setSelectedTab(TAB_ONLINE_SCREEN);
					return true;
				case R.id.menu_icon:
					if (isFirstMenuExpanded) {
						collapseFirstLevelMenu();
					} else {
						expandFirstLevelMenu(getSelectedTabId());
					}
					// 图标状态处理
					updateTabState(currentTab);
					return true;
				default:
					break;
			}
			break;

		case MotionEvent.ACTION_DOWN:
			switch (id) {
				case R.id.playbutton:
					int playerState = controllor.getPlayerState();
					if (playerState == 1) {
						playButton.setBackgroundResource(R.drawable.pausebutton);
					} else if (playerState == 2) {
						playButton.setBackgroundResource(R.drawable.playbuttonpressed);
					}
					return true;
				case R.id.nextbutton:
					nextButton.setBackgroundResource(R.drawable.nextbuttonpressed);
					return true;
				case R.id.previousbutton:
					previousButton.setBackgroundResource(R.drawable.previousbuttonpressed);
					return true;
				case R.id.playscreen_icon:
					playScreenButton.setBackgroundResource(R.drawable.playscreenfocus);
					return true;
				case R.id.listscreen_icon:
					listScreenButton.setBackgroundResource(R.drawable.listscreenfocus);
					return true;
				case R.id.onlinescreen_icon:
					onlineScreenButton.setBackgroundResource(R.drawable.onlinescreenfocus);
					return true;
				case R.id.menu_icon:
					menuButton.setBackgroundResource(R.drawable.menuiconfocus);
					return true;
				default:
					break;
			}
			break;
		default:
			break;
	}
	/*以下注释是错误的示例*/
	// if (v == listView) {
	// if (onTouchEvent(event)) {
	// return true;
	// } else if (event.getAction() == MotionEvent.ACTION_UP) {
	// } else if (event.getAction() == MotionEvent.ACTION_DOWN) {
	// }
	// } else if (event.getAction() == MotionEvent.ACTION_UP) {
	// if (v == playButton) {
	// int playerState = controllor.playOrPause();
	// updatePlayButtonState(playerState);
	// return true;
	// } else if (v == nextButton) {
	// nextButton.setBackgroundResource(R.drawable.nextbutton);
	// if (executedLongPressed) {
	// executedLongPressed = false;
	// } else {
	// controllor.next();
	// }
	// return true;
	// } else if (v == previousButton) {
	// previousButton.setBackgroundResource(R.drawable.previousbutton);
	// if (executedLongPressed) {
	// executedLongPressed = false;
	// } else {
	// controllor.previous();
	// }
	// return true;
	// } else if (v == playScreenButton) {
	// // 导航栏控制响应
	// setSelectedTab(TAB_PLAY_SCREEN);
	// return true;
	// } else if (v == listScreenButton) {
	// setSelectedTab(TAB_LIST_SCREEN);
	// return true;
	// } else if (v == onlineScreenButton) {
	// setSelectedTab(TAB_ONLINE_SCREEN);
	// return true;
	// } else if (v == menuButton) {
	// if (isFirstMenuExpanded) {
	// collapseFirstLevelMenu();
	// } else {
	// expandFirstLevelMenu(getSelectedTabId());
	// }
	// // 图标状态处理
	// updateTabState(currentTab);
	// return true;
	// }
	// } else if (event.getAction() == MotionEvent.ACTION_DOWN) {
	// if (v == playButton) {
	// int playerState = controllor.getPlayerState();
	// if (playerState == 1) {
	// playButton.setBackgroundResource(R.drawable.pausebutton);
	// } else if (playerState == 2) {
	// playButton.setBackgroundResource(R.drawable.playbuttonpressed);
	// }
	// return true;
	// } else if (v == nextButton) {
	// nextButton.setBackgroundResource(R.drawable.nextbuttonpressed);
	// return true;
	// } else if (v == previousButton) {
	// previousButton.setBackgroundResource(R.drawable.previousbuttonpressed);
	// return true;
	// } else if (v == onlineScreenButton) {
	// onlineScreenButton.setBackgroundResource(R.drawable.onlinescreenfocus);
	// return true;
	// } else if (v == playScreenButton) {
	// playScreenButton.setBackgroundResource(R.drawable.playscreenfocus);
	// return true;
	// } else if (v == listScreenButton) {
	// listScreenButton.setBackgroundResource(R.drawable.listscreenfocus);
	// return true;
	// } else if (v == menuButton) {
	// menuButton.setBackgroundResource(R.drawable.menuiconfocus);
	// return true;
	// }
	// }
	return false;
}

3、使用实体类,避免使用接口

例如:使用ArrayList,而不使用List

4、字符串非空判断

采用如下处理:

if (s == null || s.length() == 0) {
		// TODO
}

不建议采用:

if (s == null || "".equals(s)) {
		// TODO
}

5、方法参数校验处理

对与方法的参数需要进行校验处理的,统一在该方法的内部进行校验,不建议在调用方法之前校验。

public void doSome(String s) throws Exception {
   
	if (s == null || s.length() == 0) {
		return ;
	}
   // TODO
}

五、Android字段命名建议:

  • 私有字段命名以“m”开头
  • 静态字段以“s”开头
  • 公共静态final字段命名方式为:大写+“_”的方式 ALL_CAPS_WITH_UNDERSCORES.
  • 其他字段命名使用“驼峰式”命名,小写开头

六、注释范例

/**
 * 类注释,说明类的作用
 * 
 * @version 2010-9-13 下午02:20:51
 * @anchor 张汉国
 */
public class CommentTest{
	/** classVar1 documentation comment */
	public static int classVar1;

	/**
	 * 私有字段,可适用文档注释,也可以适用普通注释
	 */
	private static Object classVar2;

	/** 字段注释 */
	public Object instanceVar1;

	/** 字段注释 */
	protected int instanceVar2;

	/** 字段注释 */
	private Object[] instanceVar3;

	/**
	 * 构造方法注释,如果是带参构造函数<BR>
	 * 必须对参数进行详细说明
	 */
	public CommentTest(){
		// TODO 实现
	}

	/**
	 * 方法注释
	 */
	public void doSomething(){
		// TODO 此方法实现网络下载
		
		//局部变量
		int tHeight = 100;
		int tWidth = 100;
	}

	/**
	 * 带参方法注释
	 * 
	 * @param someParam 参数描述
	 */
	public void doSomethingElse(Object someParam){
		// ...implementation goes here...
	}

	/**
	 * 有返回值的方法注释
	 * 
	 * @param height 高度
	 * @return 如果height < 100,返回 null
	 */
	public Object doSomethingReturn(Object height){
		return null;
	}

}

附录一、常用View控件缩写对照表

控件全名 缩写 描述
Button btn 按钮
TextView txt 文本
EditText edt 输入控件
ImageButton ibtn 按钮
ImageView img 图片
ListView list 列表
GridView grid 网格
ProgressBar prb 进度条
SeekBar seb 可拖动的进度条
RadioButtion rab 单选
CheckBox chb 多选
ScrollView scv 滚动视图
Spinner spn 弹出单选
ToggleButton tbtn 触发按钮