Android编码规范要求
1. 项目结构规范
采用标准的Android项目结构,按功能模块划分目录
每个模块应包含独立的build.gradle文件
资源文件按类型分类(drawable、layout、values等)
使用MVVM或MVP架构模式组织代码结构
2. 命名规范
类名使用大驼峰命名法(PascalCase)
方法名和变量名使用小驼峰命名法(camelCase)
常量使用全大写字母和下划线分隔(UPPER_CASE)
包名使用反向域名格式(com.alibaba.project)
布局文件使用下划线命名法(activity_main.xml)
3. 代码风格
每行代码不超过120个字符
方法长度控制在80行以内
类长度控制在800行以内
大括号不换行,保持阿里巴巴Java编码规范一致性
4. 注释规范
类和接口需添加类注释,包含@author、@version、@since等信息
方法需添加方法注释,说明参数、返回值和异常
复杂逻辑需添加行内注释
使用JavaDoc标准格式
业务逻辑关键点必须添加注释说明
5. 异常处理
所有Checked Exception必须显式处理
自定义异常需继承自Exception或其子类
异常信息需具有可读性和可追溯性
网络请求必须添加超时和重试机制
异常日志需包含上下文信息
6. 内存管理
及时释放资源,避免内存泄漏
使用WeakReference处理持有者引用
避免在Adapter中创建匿名内部类
合理使用缓存机制
Context使用规范,避免静态持有Activity引用
7. 性能优化
避免在主线程执行耗时操作
使用异步加载和缓存机制
合理使用View复用机制
避免频繁的findViewById调用,推荐使用ViewBinding
图片加载使用Glide等成熟框架
RecyclerView优化,合理设置setHasFixedSize和setItemViewCacheSize
8. 安全规范
敏感信息需加密存储
网络请求需使用HTTPS协议
输入参数需进行合法性校验
权限申请需遵循Android权限模型
WebView需添加安全配置,禁用file协议等
签名发布必须使用正式签名
9. 测试规范
单元测试覆盖率不低于80%
集成测试需覆盖核心业务流程
使用Mockito进行依赖模拟
测试用例需具有可重复性和可维护性
UI测试使用Espresso框架
10. 版本控制
提交信息需清晰描述修改内容,遵循"类型: 描述"格式
分支管理采用Git Flow模型
代码审查需通过Pull Request机制
版本号遵循语义化版本控制
发布前必须进行Code Review
11. 网络通信规范
使用Retrofit+OkHttp进行网络请求
网络请求必须添加统一拦截器处理公共参数
响应数据使用Gson或FastJson解析
网络状态需进行判断和提示
接口设计遵循RESTful规范
12. 数据存储规范
SharedPreferences用于存储简单配置信息
SQLite数据库使用Room框架
文件存储需考虑存储权限和路径适配
大数据量存储考虑分库分表策略
数据库升级需提供Migration策略
13. 多线程规范
主线程只处理UI相关操作
耗时操作使用线程池或AsyncTask
线程间通信使用Handler或LiveData
避免线程死锁和资源竞争
线程池配置需根据业务场景合理设置
14. UI设计规范
遵循Material Design设计规范
适配不同屏幕尺寸和分辨率
使用ConstraintLayout优化布局性能
动画效果需流畅自然
颜色、字体、间距统一使用资源文件定义
15. 日志规范
使用统一的日志工具类
日志级别合理使用(DEBUG/INFO/WARN/ERROR)
生产环境禁止输出DEBUG级别日志
日志信息需包含时间、线程、类名等信息
敏感信息不得输出到日志中
2. 项目结构规范
2.1 目录结构
project/
├── app/
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/
│ │ │ ├── res/
│ │ │ └── AndroidManifest.xml
│ │ └── test/
│ └── build.gradle
├── module1/
├── module2/
└── build.gradle
2.2 包结构
com.alibaba.projectname
├── base // 基础组件
├── common // 公共工具类
├── feature // 功能模块
├── network // 网络相关
├── database // 数据库相关
└── ui // 界面相关
3. 命名规范
3.1 类命名
- Activity类:以Activity结尾(如MainActivity)
- Fragment类:以Fragment结尾(如HomeFragment)
- Service类:以Service结尾(如DownloadService)
- BroadcastReceiver类:以Receiver结尾(如NetworkReceiver)
- 自定义View:以所继承的View类名结尾(如CustomTextView)
3.2 方法命名
- 获取数据:get+字段名(如getUserName)
- 设置数据:set+字段名(如setUserName)
- 判断布尔值:is+字段名(如isEnabled)
- 事件处理:on+事件名(如onClick)
3.3 变量命名
- 成员变量:变量名(如userName) 具有具体意义,避免: aaa,bbb,abc123
- 静态变量:变量名(如Instance_Path) 具有具体意义
- 常量:全大写+下划线(如MAX_COUNT) 具有具体意义
3.4 资源文件命名
- 布局文件:模块_功能.xml(如activity_main.xml)
- 图片资源:功能_状态_大小.png(如btn_login_normal.9.png)
- 字符串资源:模块_功能(如login_username_hint)
- 颜色资源:颜色_用途(如color_primary)
4. 代码风格
4.1 缩进与空格
java
// 正确示例
public class MainActivity extends AppCompatActivity {
private String userName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (userName != null) {
// do something
}
}
}
4.2 行长度限制
- 每行代码不超过120个字符
- 超长语句需要合理换行
4.3 空行规范
- 方法之间空一行
- 逻辑块之间空一行
- 类成员变量与方法之间空两行
5. 注释规范
5.1 类注释
java
/**
* 主界面Activity
* 负责展示首页内容和导航功能
*
* @author ZhangSan
* @version 1.0.0
* @since 2023-01-01
*/
public class MainActivity extends AppCompatActivity {
// ...
}
5.2 方法注释
java
/**
* 初始化用户界面
* 设置布局和基础组件
*
* @param savedInstanceState 保存的状态数据
* @throws IllegalStateException 当布局文件不存在时抛出
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
}
5.3 行内注释
java
// 网络请求超时设置为30秒
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.build();
6. 异常处理
6.1 异常捕获
java
try {
// 可能出现异常的代码
String result = networkRequest.execute();
} catch (IOException e) {
// 处理网络异常
Log.e(TAG, "网络请求失败", e);
showNetworkError();
} catch (JSONException e) {
// 处理JSON解析异常
Log.e(TAG, "数据解析失败", e);
showDataError();
} finally {
// 释放资源
if (networkRequest != null) {
networkRequest.cancel();
}
}
6.2 自定义异常
java
public class NetworkException extends Exception {
private int errorCode;
public NetworkException(String message, int errorCode) {
super(message);
this.errorCode = errorCode;
}
public int getErrorCode() {
return errorCode;
}
}
7. 内存管理
7.1 Context使用
java
public class DataManager {
private Context context; // 避免持有Activity引用
public DataManager(Context context) {
// 使用ApplicationContext避免内存泄漏
this.context = context.getApplicationContext();
}
}
7.2 资源释放
java
public class ImageLoader {
private ExecutorService executor;
public void onDestroy() {
if (executor != null && !executor.isShutdown()) {
executor.shutdown();
}
}
}
7.3 Handler使用
java
public class MainActivity extends AppCompatActivity {
private static class SafeHandler extends Handler {
private final WeakReference<MainActivity> activityRef;
SafeHandler(MainActivity activity) {
activityRef = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = activityRef.get();
if (activity != null) {
// 处理消息
}
}
}
private SafeHandler mHandler = new SafeHandler(this);
}
8. 性能优化
8.1 布局优化
xml
<!-- 使用ConstraintLayout减少嵌套 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
8.2 RecyclerView优化
java
public class UserAdapter extends RecyclerView.Adapter<UserAdapter.ViewHolder> {
// 合理设置缓存大小
private static final int CACHE_SIZE = 20;
static class ViewHolder extends RecyclerView.ViewHolder {
TextView nameText;
ImageView avatarImage;
ViewHolder(View itemView) {
super(itemView);
nameText = itemView.findViewById(R.id.text_name);
avatarImage = itemView.findViewById(R.id.image_avatar);
}
}
}
8.3 图片加载优化
java
// 使用Glide加载图片
Glide.with(context)
.load(imageUrl)
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(imageView);
9. 安全规范
9.1 数据存储安全
java
// 敏感数据加密存储
public class SecureStorage {
private static final String TRANSFORMATION = "AES/GCM/NoPadding";
public void saveSecureData(String key, String data) {
try {
// 加密处理
String encryptedData = encrypt(data);
SharedPreferences prefs = context.getSharedPreferences("secure_prefs", Context.MODE_PRIVATE);
prefs.edit().putString(key, encryptedData).apply();
} catch (Exception e) {
Log.e(TAG, "数据加密失败", e);
}
}
}
9.2 网络安全
java
// HTTPS配置
public class SecureHttpClient {
public OkHttpClient createSecureClient() {
return new OkHttpClient.Builder()
.connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS))
.certificatePinner(new CertificatePinner.Builder()
.add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build())
.build();
}
}
9.3 权限管理
java
// 运行时权限申请
public class PermissionHelper {
public static void requestCameraPermission(Activity activity, int requestCode) {
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.CAMERA},
requestCode);
}
}
}
10. 测试规范
10.1 单元测试
java
@RunWith(MockitoJUnitRunner.class)
public class UserManagerTest {
@Mock
private UserRepository mockRepository;
@InjectMocks
private UserManager userManager;
@Test
public void testGetUserById() {
// Given
User expectedUser = new User("123", "张三");
when(mockRepository.getUserById("123")).thenReturn(expectedUser);
// When
User actualUser = userManager.getUserById("123");
// Then
assertEquals(expectedUser, actualUser);
verify(mockRepository).getUserById("123");
}
}
10.2 UI测试
java
@RunWith(AndroidJUnit4.class)
public class LoginActivityTest {
@Rule
public ActivityTestRule<LoginActivity> activityRule =
new ActivityTestRule<>(LoginActivity.class);
@Test
public void testLoginSuccess() {
// 输入用户名和密码
onView(withId(R.id.edit_username))
.perform(typeText("testuser"), closeSoftKeyboard());
onView(withId(R.id.edit_password))
.perform(typeText("password"), closeSoftKeyboard());
// 点击登录按钮
onView(withId(R.id.btn_login)).perform(click());
// 验证跳转到主界面
intended(hasComponent(MainActivity.class.getName()));
}
}
11. 版本控制
11.1 提交信息规范
feat: 添加用户登录功能
fix: 修复网络请求超时问题
opt: 优化代码
docs: 更新README文档
style: 调整代码格式
refactor: 重构数据处理模块
test: 添加单元测试用例
chore: 更新依赖版本
11.2 分支管理
master # 生产环境分支
develop # 开发环境分支
feature/xxx # 功能开发分支
hotfix/xxx # 紧急修复分支
release/xxx # 发布准备分支
12. 网络通信规范
12.1 Retrofit接口定义
java
public interface ApiService {
@GET("users/{id}")
Call<User> getUser(@Path("id") String userId);
@POST("users")
Call<User> createUser(@Body User user);
@PUT("users/{id}")
Call<User> updateUser(@Path("id") String userId, @Body User user);
@DELETE("users/{id}")
Call<ResponseBody> deleteUser(@Path("id") String userId);
}
12.2 拦截器配置
java
public class AuthInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("Authorization", "Bearer " + getToken())
.header("Content-Type", "application/json")
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
}
13. 数据存储规范
13.1 Room数据库
java
@Entity(tableName = "users")
public class User {
@PrimaryKey
@NonNull
private String id;
@ColumnInfo(name = "user_name")
private String userName;
@ColumnInfo(name = "created_at")
private long createdAt;
// getter和setter方法
}
@Dao
public interface UserDao {
@Query("SELECT * FROM users")
List<User> getAllUsers();
@Insert
void insertUser(User user);
@Update
void updateUser(User user);
@Delete
void deleteUser(User user);
}
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
14. 多线程规范
14.1 线程池使用
java
public class ThreadPoolManager {
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "ThreadPoolManager #" + mCount.getAndIncrement());
}
};
private static final ExecutorService THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(128), sThreadFactory);
public static ExecutorService getThreadPool() {
return THREAD_POOL_EXECUTOR;
}
}
15. UI设计规范
15.1 Material Design
xml
<!-- 使用Material Design组件 -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardElevation="4dp"
app:cardCornerRadius="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题"
android:textAppearance="?attr/textAppearanceHeadline6" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
16. 日志规范
16.1 日志工具类
java
public class LogUtils {
private static final String TAG = "AliApp";
private static final boolean DEBUG = BuildConfig.DEBUG;
public static void d(String message) {
if (DEBUG) {
Log.d(TAG, message);
}
}
public static void i(String message) {
Log.i(TAG, message);
}
public static void w(String message) {
Log.w(TAG, message);
}
public static void e(String message, Throwable throwable) {
Log.e(TAG, message, throwable);
}
}