From 580cd5adb0fad159453cc5a074a2be649fc6a446 Mon Sep 17 00:00:00 2001 From: renjianbo <18691577328@163.com> Date: Fri, 16 Jan 2026 14:54:07 +0800 Subject: [PATCH] =?UTF-8?q?=E9=8F=87=E5=AD=98=E6=9F=8A=E9=8F=82=E5=9B=A8?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .obsidian/workspace.json | 49 +- docs/Google开发文档体系/API参考/系统API.md | 1054 +++++++++++- .../最佳实践/应用架构最佳实践.md | 789 ++++++++- .../最佳实践/性能优化最佳实践.md | 720 +++++++- .../最佳实践/用户体验最佳实践.md | 792 ++++++++- .../Projects/saars开发/aiapply/未命名 1.md | 1241 ++++++++++++++ .../Projects/saars开发/aiapply/未命名.md | 183 ++ docs/android面试/系统原理/WMS面试.md | 1475 +++++++++++++++++ docs/dify/用户注册及添加成员.md | 1345 +++++++++++++++ mkdocs.yml | 4 + 10 files changed, 7611 insertions(+), 41 deletions(-) create mode 100644 docs/Obsidian笔记体系/Projects/saars开发/aiapply/未命名 1.md create mode 100644 docs/Obsidian笔记体系/Projects/saars开发/aiapply/未命名.md create mode 100644 docs/android面试/系统原理/WMS面试.md create mode 100644 docs/dify/用户注册及添加成员.md diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index da20117..0887372 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -13,15 +13,30 @@ "state": { "type": "markdown", "state": { - "file": "docs/Obsidian笔记体系/Areas/09-调试与工具链/Systrace_Perfetto全解读.md", + "file": "docs/dify/用户注册及添加成员.md", "mode": "source", "source": false }, "icon": "lucide-file", - "title": "Systrace_Perfetto全解读" + "title": "用户注册及添加成员" + } + }, + { + "id": "25c9f7051aac05b3", + "type": "leaf", + "state": { + "type": "markdown", + "state": { + "file": "docs/android面试/系统原理/WMS面试.md", + "mode": "source", + "source": false + }, + "icon": "lucide-file", + "title": "WMS面试" } } - ] + ], + "currentTab": 1 } ], "direction": "vertical" @@ -174,17 +189,27 @@ }, "left-ribbon": { "hiddenItems": { + "bases:新建数据库": false, "switcher:打开快速切换": false, "graph:查看关系图谱": false, "canvas:新建白板": false, "daily-notes:打开/创建今天的日记": false, "templates:插入模板": false, - "command-palette:打开命令面板": false, - "bases:创建新数据库": false + "command-palette:打开命令面板": false } }, - "active": "5b497a77c6d68c73", + "active": "25c9f7051aac05b3", "lastOpenFiles": [ + "docs/Obsidian笔记体系/Projects/saars开发/aiapply/未命名 1.md", + "docs/android面试/系统原理/WMS面试.md", + "docs/Obsidian笔记体系/Projects/saars开发/aiapply/未命名.md", + "docs/Obsidian笔记体系/Projects/saars开发/aiapply", + "docs/dify/管理员账户.md", + "docs/dify/用户注册及添加成员.md", + "docs/dify/密码输入错误次数超过限制时的机制.md", + "docs/dify/使用dify,可以生成一个专项事务助手吗,比如公司正规化事务助手.md", + "docs/dify/作为安卓高级开发工程师,除了项目管理,你完全可以在技术专项、团队效能和个人成长三大领域构建更懂你的专属助手.md", + "docs/Obsidian笔记体系/Areas/09-调试与工具链/Systrace_Perfetto全解读.md", "docs/技术面试问题回答.md", "docs/Google开发文档体系/视频和教程/技术会议.md", "docs/Google开发文档体系/视频和教程/官方视频教程.md", @@ -202,15 +227,6 @@ "docs/Google开发文档体系/示例代码/架构示例.md", "docs/Google开发文档体系/示例代码/官方示例项目.md", "docs/Google开发文档体系/示例代码/代码片段.md", - "docs/Google开发文档体系/最佳实践/用户体验最佳实践.md", - "docs/Google开发文档体系/最佳实践/应用架构最佳实践.md", - "docs/Google开发文档体系/最佳实践/性能优化最佳实践.md", - "docs/Google开发文档体系/最佳实践/安全最佳实践.md", - "docs/Google开发文档体系/最佳实践/代码质量最佳实践.md", - "docs/Google开发文档体系/工具和资源/调试工具.md", - "docs/Google开发文档体系/工具和资源/构建系统.md", - "docs/Google开发文档体系/工具和资源/Android_Studio.md", - "docs/Google开发文档体系/工具和资源/性能分析工具.md", "docs/Google开发文档体系/视频和教程", "docs/Google开发文档体系/核心主题", "docs/Google开发文档体系/示例代码", @@ -219,7 +235,6 @@ "docs/Google开发文档体系/入门指南", "docs/Google开发文档体系/API参考", "docs/Google开发文档体系", - "docs/android面试/技术面试问题回答.txt", - "技术面试问题回答.txt" + "docs/android面试/技术面试问题回答.txt" ] } \ No newline at end of file diff --git a/docs/Google开发文档体系/API参考/系统API.md b/docs/Google开发文档体系/API参考/系统API.md index 294e48d..8ae9180 100644 --- a/docs/Google开发文档体系/API参考/系统API.md +++ b/docs/Google开发文档体系/API参考/系统API.md @@ -1,8 +1,1052 @@ # 系统API -## 待补充内容 +系统API是Android平台提供的系统级服务接口,用于访问系统功能、管理权限、获取系统信息等。本文档介绍Android系统API的使用方法。 -- 系统服务API -- 系统权限API -- 系统功能API -- 系统版本API +## 目录 + +- [系统服务API](#系统服务api) +- [系统权限API](#系统权限api) +- [系统功能API](#系统功能api) +- [系统版本API](#系统版本api) + +--- + +## 系统服务API + +### 1. ActivityManager + +ActivityManager用于管理Activity和任务栈。 + +#### 获取ActivityManager + +```java +// 获取ActivityManager实例 +ActivityManager activityManager = (ActivityManager) + getSystemService(Context.ACTIVITY_SERVICE); +``` + +#### 常用方法 + +```java +// 获取运行中的应用列表 +List runningApps = + activityManager.getRunningAppProcesses(); + +// 获取内存信息 +ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); +activityManager.getMemoryInfo(memoryInfo); +long totalMemory = memoryInfo.totalMem; +long availableMemory = memoryInfo.availMem; +boolean lowMemory = memoryInfo.lowMemory; + +// 获取任务栈信息 +List runningTasks = + activityManager.getRunningTasks(10); + +// 获取应用任务信息 +List appTasks = + activityManager.getAppTasks(); +``` + +#### 使用示例 + +```kotlin +class SystemInfoActivity : AppCompatActivity() { + private lateinit var activityManager: ActivityManager + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_system_info) + + activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager + + // 获取内存信息 + val memoryInfo = ActivityManager.MemoryInfo() + activityManager.getMemoryInfo(memoryInfo) + + val totalMemoryMB = memoryInfo.totalMem / (1024 * 1024) + val availableMemoryMB = memoryInfo.availMem / (1024 * 1024) + + Log.d("Memory", "总内存: ${totalMemoryMB}MB") + Log.d("Memory", "可用内存: ${availableMemoryMB}MB") + Log.d("Memory", "低内存: ${memoryInfo.lowMemory}") + } +} +``` + +### 2. WindowManager + +WindowManager用于管理窗口和显示。 + +#### 获取WindowManager + +```java +WindowManager windowManager = (WindowManager) + getSystemService(Context.WINDOW_SERVICE); +``` + +#### 常用方法 + +```java +// 获取默认显示信息 +Display display = windowManager.getDefaultDisplay(); +DisplayMetrics metrics = new DisplayMetrics(); +display.getMetrics(metrics); + +int width = metrics.widthPixels; +int height = metrics.heightPixels; +float density = metrics.density; +int densityDpi = metrics.densityDpi; + +// 添加窗口 +WindowManager.LayoutParams params = new WindowManager.LayoutParams( + WindowManager.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.TYPE_APPLICATION, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, + PixelFormat.TRANSLUCENT +); +windowManager.addView(view, params); + +// 移除窗口 +windowManager.removeView(view); +``` + +#### 使用示例 + +```kotlin +class WindowManagerActivity : AppCompatActivity() { + private lateinit var windowManager: WindowManager + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_window_manager) + + windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager + + // 获取屏幕信息 + val display = windowManager.defaultDisplay + val metrics = DisplayMetrics() + display.getMetrics(metrics) + + Log.d("Display", "屏幕宽度: ${metrics.widthPixels}px") + Log.d("Display", "屏幕高度: ${metrics.heightPixels}px") + Log.d("Display", "屏幕密度: ${metrics.density}") + Log.d("Display", "DPI: ${metrics.densityDpi}") + } +} +``` + +### 3. NotificationManager + +NotificationManager用于管理通知。 + +#### 获取NotificationManager + +```java +NotificationManager notificationManager = (NotificationManager) + getSystemService(Context.NOTIFICATION_SERVICE); +``` + +#### 创建通知渠道(Android 8.0+) + +```java +if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + String channelId = "my_channel_id"; + String channelName = "My Channel"; + int importance = NotificationManager.IMPORTANCE_DEFAULT; + + NotificationChannel channel = new NotificationChannel( + channelId, channelName, importance + ); + channel.setDescription("Channel description"); + + notificationManager.createNotificationChannel(channel); +} +``` + +#### 发送通知 + +```java +// 创建通知 +NotificationCompat.Builder builder = new NotificationCompat.Builder( + context, "my_channel_id" +) + .setSmallIcon(R.drawable.ic_notification) + .setContentTitle("通知标题") + .setContentText("通知内容") + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setAutoCancel(true); + +// 发送通知 +int notificationId = 1; +notificationManager.notify(notificationId, builder.build()); + +// 取消通知 +notificationManager.cancel(notificationId); +``` + +#### 使用示例 + +```kotlin +class NotificationActivity : AppCompatActivity() { + private lateinit var notificationManager: NotificationManager + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_notification) + + notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) + as NotificationManager + + // 创建通知渠道(Android 8.0+) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val channel = NotificationChannel( + "my_channel_id", + "My Channel", + NotificationManager.IMPORTANCE_DEFAULT + ).apply { + description = "Channel description" + } + notificationManager.createNotificationChannel(channel) + } + + // 发送通知 + button.setOnClickListener { + showNotification() + } + } + + private fun showNotification() { + val builder = NotificationCompat.Builder(this, "my_channel_id") + .setSmallIcon(R.drawable.ic_notification) + .setContentTitle("通知标题") + .setContentText("通知内容") + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setAutoCancel(true) + + notificationManager.notify(1, builder.build()) + } +} +``` + +### 4. LocationManager + +LocationManager用于管理位置服务。 + +#### 获取LocationManager + +```java +LocationManager locationManager = (LocationManager) + getSystemService(Context.LOCATION_SERVICE); +``` + +#### 检查位置服务是否可用 + +```java +boolean isGpsEnabled = locationManager.isProviderEnabled( + LocationManager.GPS_PROVIDER +); +boolean isNetworkEnabled = locationManager.isProviderEnabled( + LocationManager.NETWORK_PROVIDER +); +``` + +#### 请求位置更新 + +```java +// 检查权限 +if (ContextCompat.checkSelfPermission(this, + Manifest.permission.ACCESS_FINE_LOCATION) + != PackageManager.PERMISSION_GRANTED) { + // 请求权限 + return; +} + +// 请求位置更新 +LocationListener locationListener = new LocationListener() { + @Override + public void onLocationChanged(Location location) { + double latitude = location.getLatitude(); + double longitude = location.getLongitude(); + float accuracy = location.getAccuracy(); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) {} + + @Override + public void onProviderEnabled(String provider) {} + + @Override + public void onProviderDisabled(String provider) {} +}; + +locationManager.requestLocationUpdates( + LocationManager.GPS_PROVIDER, + 1000, // 最小时间间隔(毫秒) + 10, // 最小距离(米) + locationListener +); + +// 停止位置更新 +locationManager.removeUpdates(locationListener); +``` + +#### 使用示例 + +```kotlin +class LocationActivity : AppCompatActivity() { + private lateinit var locationManager: LocationManager + private lateinit var locationListener: LocationListener + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_location) + + locationManager = getSystemService(Context.LOCATION_SERVICE) + as LocationManager + + locationListener = object : LocationListener { + override fun onLocationChanged(location: Location) { + val latitude = location.latitude + val longitude = location.longitude + val accuracy = location.accuracy + + Log.d("Location", "纬度: $latitude, 经度: $longitude, 精度: $accuracy") + } + + override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {} + override fun onProviderEnabled(provider: String) {} + override fun onProviderDisabled(provider: String) {} + } + + // 检查权限 + if (ContextCompat.checkSelfPermission(this, + Manifest.permission.ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED) { + startLocationUpdates() + } else { + // 请求权限 + ActivityCompat.requestPermissions( + this, + arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), + REQUEST_LOCATION_PERMISSION + ) + } + } + + private fun startLocationUpdates() { + locationManager.requestLocationUpdates( + LocationManager.GPS_PROVIDER, + 1000L, + 10f, + locationListener + ) + } + + override fun onDestroy() { + super.onDestroy() + locationManager.removeUpdates(locationListener) + } + + companion object { + private const val REQUEST_LOCATION_PERMISSION = 100 + } +} +``` + +### 5. TelephonyManager + +TelephonyManager用于访问电话相关信息。 + +#### 获取TelephonyManager + +```java +TelephonyManager telephonyManager = (TelephonyManager) + getSystemService(Context.TELEPHONY_SERVICE); +``` + +#### 常用方法 + +```java +// 获取设备ID(需要READ_PHONE_STATE权限) +String deviceId = telephonyManager.getDeviceId(); + +// 获取SIM卡信息 +String simSerialNumber = telephonyManager.getSimSerialNumber(); +String simOperatorName = telephonyManager.getSimOperatorName(); +String networkOperatorName = telephonyManager.getNetworkOperatorName(); + +// 获取网络类型 +int networkType = telephonyManager.getNetworkType(); +// NETWORK_TYPE_LTE, NETWORK_TYPE_UMTS, etc. + +// 检查电话功能 +boolean isPhone = telephonyManager.getPhoneType() != + TelephonyManager.PHONE_TYPE_NONE; +``` + +#### 使用示例 + +```kotlin +class TelephonyActivity : AppCompatActivity() { + private lateinit var telephonyManager: TelephonyManager + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_telephony) + + telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) + as TelephonyManager + + // 检查权限 + if (ContextCompat.checkSelfPermission(this, + Manifest.permission.READ_PHONE_STATE) + == PackageManager.PERMISSION_GRANTED) { + getTelephonyInfo() + } + } + + private fun getTelephonyInfo() { + val deviceId = telephonyManager.deviceId + val simOperatorName = telephonyManager.simOperatorName + val networkOperatorName = telephonyManager.networkOperatorName + val networkType = telephonyManager.networkType + + Log.d("Telephony", "设备ID: $deviceId") + Log.d("Telephony", "SIM运营商: $simOperatorName") + Log.d("Telephony", "网络运营商: $networkOperatorName") + Log.d("Telephony", "网络类型: $networkType") + } +} +``` + +### 6. PowerManager + +PowerManager用于管理电源和唤醒锁。 + +#### 获取PowerManager + +```java +PowerManager powerManager = (PowerManager) + getSystemService(Context.POWER_SERVICE); +``` + +#### 唤醒锁 + +```java +// 获取唤醒锁 +PowerManager.WakeLock wakeLock = powerManager.newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK, + "MyApp::MyWakeLock" +); + +// 获取唤醒锁 +wakeLock.acquire(); + +// 释放唤醒锁 +wakeLock.release(); + +// 检查是否持有唤醒锁 +boolean isHeld = wakeLock.isHeld(); +``` + +#### 使用示例 + +```kotlin +class PowerManagerActivity : AppCompatActivity() { + private lateinit var powerManager: PowerManager + private var wakeLock: PowerManager.WakeLock? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_power_manager) + + powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager + + // 创建唤醒锁 + wakeLock = powerManager.newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK, + "MyApp::MyWakeLock" + ) + } + + private fun acquireWakeLock() { + wakeLock?.acquire(10 * 60 * 1000L) // 10分钟超时 + } + + private fun releaseWakeLock() { + wakeLock?.let { + if (it.isHeld) { + it.release() + } + } + } + + override fun onDestroy() { + super.onDestroy() + releaseWakeLock() + } +} +``` + +--- + +## 系统权限API + +### 1. 权限检查 + +#### 检查权限 + +```java +// 检查单个权限 +int result = ContextCompat.checkSelfPermission( + context, + Manifest.permission.CAMERA +); + +boolean hasPermission = result == PackageManager.PERMISSION_GRANTED; + +// 检查多个权限 +String[] permissions = { + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE +}; + +int[] results = new int[permissions.length]; +for (int i = 0; i < permissions.length; i++) { + results[i] = ContextCompat.checkSelfPermission( + context, + permissions[i] + ); +} +``` + +#### 使用示例 + +```kotlin +class PermissionActivity : AppCompatActivity() { + private fun checkPermission(permission: String): Boolean { + return ContextCompat.checkSelfPermission( + this, + permission + ) == PackageManager.PERMISSION_GRANTED + } + + private fun checkPermissions(permissions: Array): Boolean { + return permissions.all { checkPermission(it) } + } +} +``` + +### 2. 权限申请 + +#### 请求权限 + +```java +// 请求单个权限 +ActivityCompat.requestPermissions( + activity, + new String[]{Manifest.permission.CAMERA}, + REQUEST_CODE_CAMERA +); + +// 请求多个权限 +ActivityCompat.requestPermissions( + activity, + new String[]{ + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE + }, + REQUEST_CODE_PERMISSIONS +); + +// 处理权限结果 +@Override +public void onRequestPermissionsResult( + int requestCode, + @NonNull String[] permissions, + @NonNull int[] grantResults +) { + if (requestCode == REQUEST_CODE_CAMERA) { + if (grantResults.length > 0 && + grantResults[0] == PackageManager.PERMISSION_GRANTED) { + // 权限已授予 + } else { + // 权限被拒绝 + } + } +} +``` + +#### 使用示例 + +```kotlin +class PermissionActivity : AppCompatActivity() { + companion object { + private const val REQUEST_CODE_CAMERA = 100 + private const val REQUEST_CODE_PERMISSIONS = 101 + } + + private fun requestPermission(permission: String, requestCode: Int) { + ActivityCompat.requestPermissions( + this, + arrayOf(permission), + requestCode + ) + } + + private fun requestPermissions(permissions: Array, requestCode: Int) { + ActivityCompat.requestPermissions( + this, + permissions, + requestCode + ) + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + + when (requestCode) { + REQUEST_CODE_CAMERA -> { + if (grantResults.isNotEmpty() && + grantResults[0] == PackageManager.PERMISSION_GRANTED) { + // 权限已授予 + openCamera() + } else { + // 权限被拒绝 + showPermissionDeniedMessage() + } + } + } + } +} +``` + +### 3. 权限说明 + +#### 显示权限说明 + +```java +// 检查是否需要显示权限说明 +if (ActivityCompat.shouldShowRequestPermissionRationale( + activity, + Manifest.permission.CAMERA)) { + // 显示说明对话框 + showPermissionRationale(); +} else { + // 直接请求权限 + ActivityCompat.requestPermissions( + activity, + new String[]{Manifest.permission.CAMERA}, + REQUEST_CODE_CAMERA + ); +} +``` + +#### 使用示例 + +```kotlin +class PermissionActivity : AppCompatActivity() { + private fun requestPermissionWithRationale(permission: String, requestCode: Int) { + if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) { + // 显示说明对话框 + MaterialAlertDialogBuilder(this) + .setTitle("需要权限") + .setMessage("此功能需要相机权限才能使用") + .setPositiveButton("确定") { _, _ -> + ActivityCompat.requestPermissions( + this, + arrayOf(permission), + requestCode + ) + } + .setNegativeButton("取消", null) + .show() + } else { + // 直接请求权限 + ActivityCompat.requestPermissions( + this, + arrayOf(permission), + requestCode + ) + } + } +} +``` + +--- + +## 系统功能API + +### 1. 文件系统API + +#### 访问外部存储 + +```java +// 检查外部存储是否可用 +boolean isExternalStorageAvailable = Environment.getExternalStorageState() + .equals(Environment.MEDIA_MOUNTED); + +// 获取外部存储目录 +File externalStorageDir = Environment.getExternalStorageDirectory(); +File downloadsDir = Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_DOWNLOADS +); + +// 获取应用专用外部存储目录 +File appExternalDir = getExternalFilesDir(null); +File appPicturesDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); +``` + +#### 使用示例 + +```kotlin +class FileSystemActivity : AppCompatActivity() { + private fun getExternalStorageInfo() { + // 检查外部存储状态 + val state = Environment.getExternalStorageState() + val isAvailable = state == Environment.MEDIA_MOUNTED + + if (isAvailable) { + // 获取外部存储目录 + val externalStorageDir = Environment.getExternalStorageDirectory() + val downloadsDir = Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_DOWNLOADS + ) + + // 获取应用专用目录 + val appExternalDir = getExternalFilesDir(null) + val appPicturesDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES) + + Log.d("Storage", "外部存储: ${externalStorageDir.absolutePath}") + Log.d("Storage", "下载目录: ${downloadsDir.absolutePath}") + Log.d("Storage", "应用外部目录: ${appExternalDir?.absolutePath}") + } + } +} +``` + +### 2. 网络API + +#### 检查网络连接 + +```java +ConnectivityManager connectivityManager = (ConnectivityManager) + getSystemService(Context.CONNECTIVITY_SERVICE); + +// 检查网络连接 +NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); +boolean isConnected = networkInfo != null && networkInfo.isConnected(); + +// 获取网络类型 +int networkType = networkInfo.getType(); +// ConnectivityManager.TYPE_WIFI +// ConnectivityManager.TYPE_MOBILE +``` + +#### 使用示例 + +```kotlin +class NetworkActivity : AppCompatActivity() { + private lateinit var connectivityManager: ConnectivityManager + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_network) + + connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) + as ConnectivityManager + + checkNetworkConnection() + } + + private fun checkNetworkConnection() { + val networkInfo = connectivityManager.activeNetworkInfo + val isConnected = networkInfo != null && networkInfo.isConnected + + if (isConnected) { + val networkType = networkInfo.type + when (networkType) { + ConnectivityManager.TYPE_WIFI -> { + Log.d("Network", "WiFi连接") + } + ConnectivityManager.TYPE_MOBILE -> { + Log.d("Network", "移动网络连接") + } + } + } else { + Log.d("Network", "无网络连接") + } + } +} +``` + +### 3. 传感器API + +#### 使用传感器 + +```java +SensorManager sensorManager = (SensorManager) + getSystemService(Context.SENSOR_SERVICE); + +// 获取传感器 +Sensor accelerometer = sensorManager.getDefaultSensor( + Sensor.TYPE_ACCELEROMETER +); + +// 注册传感器监听器 +SensorEventListener listener = new SensorEventListener() { + @Override + public void onSensorChanged(SensorEvent event) { + float x = event.values[0]; + float y = event.values[1]; + float z = event.values[2]; + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) {} +}; + +sensorManager.registerListener( + listener, + accelerometer, + SensorManager.SENSOR_DELAY_NORMAL +); + +// 取消注册 +sensorManager.unregisterListener(listener); +``` + +#### 使用示例 + +```kotlin +class SensorActivity : AppCompatActivity() { + private lateinit var sensorManager: SensorManager + private var accelerometer: Sensor? = null + private val sensorListener = object : SensorEventListener { + override fun onSensorChanged(event: SensorEvent) { + val x = event.values[0] + val y = event.values[1] + val z = event.values[2] + + Log.d("Sensor", "X: $x, Y: $y, Z: $z") + } + + override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {} + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_sensor) + + sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager + accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) + } + + override fun onResume() { + super.onResume() + accelerometer?.let { + sensorManager.registerListener( + sensorListener, + it, + SensorManager.SENSOR_DELAY_NORMAL + ) + } + } + + override fun onPause() { + super.onPause() + sensorManager.unregisterListener(sensorListener) + } +} +``` + +--- + +## 系统版本API + +### 1. 获取系统版本信息 + +#### 系统版本 + +```java +// 获取Android版本号 +int sdkVersion = Build.VERSION.SDK_INT; +String sdkVersionName = Build.VERSION.RELEASE; // "13", "12", etc. + +// 获取设备信息 +String manufacturer = Build.MANUFACTURER; // "Samsung", "Google", etc. +String model = Build.MODEL; // "Pixel 6", "Galaxy S21", etc. +String brand = Build.BRAND; // "google", "samsung", etc. +String device = Build.DEVICE; // "oriole", "o1q", etc. +String product = Build.PRODUCT; // "oriole", "o1q", etc. +``` + +#### 使用示例 + +```kotlin +class SystemVersionActivity : AppCompatActivity() { + private fun getSystemVersionInfo() { + // Android版本 + val sdkVersion = Build.VERSION.SDK_INT + val sdkVersionName = Build.VERSION.RELEASE + + // 设备信息 + val manufacturer = Build.MANUFACTURER + val model = Build.MODEL + val brand = Build.BRAND + val device = Build.DEVICE + val product = Build.PRODUCT + + Log.d("System", "SDK版本: $sdkVersion") + Log.d("System", "Android版本: $sdkVersionName") + Log.d("System", "制造商: $manufacturer") + Log.d("System", "型号: $model") + Log.d("System", "品牌: $brand") + Log.d("System", "设备: $device") + Log.d("System", "产品: $product") + } +} +``` + +### 2. 版本检查 + +#### 检查Android版本 + +```java +// 检查Android版本 +if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + // Android 8.0及以上 +} + +if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + // Android 9.0及以上 +} + +if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + // Android 10及以上 +} + +if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + // Android 11及以上 +} + +if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + // Android 12及以上 +} + +if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + // Android 13及以上 +} +``` + +#### 使用示例 + +```kotlin +class VersionCheckActivity : AppCompatActivity() { + private fun checkAndroidVersion() { + when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> { + // Android 13+ + Log.d("Version", "Android 13或更高版本") + } + Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + // Android 12+ + Log.d("Version", "Android 12或更高版本") + } + Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> { + // Android 11+ + Log.d("Version", "Android 11或更高版本") + } + Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> { + // Android 10+ + Log.d("Version", "Android 10或更高版本") + } + else -> { + Log.d("Version", "Android 10以下版本") + } + } + } + + private fun useNewFeature() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + // 使用Android 8.0+的新特性 + useNotificationChannel() + } else { + // 使用旧版本API + useOldNotification() + } + } +} +``` + +### 3. 应用版本信息 + +#### 获取应用版本 + +```java +try { + PackageInfo packageInfo = getPackageManager().getPackageInfo( + getPackageName(), + 0 + ); + + String versionName = packageInfo.versionName; // "1.0.0" + int versionCode = packageInfo.versionCode; // 1 + String packageName = packageInfo.packageName; // "com.example.app" + +} catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); +} +``` + +#### 使用示例 + +```kotlin +class AppVersionActivity : AppCompatActivity() { + private fun getAppVersionInfo() { + try { + val packageInfo = packageManager.getPackageInfo( + packageName, + 0 + ) + + val versionName = packageInfo.versionName + val versionCode = packageInfo.longVersionCode // API 28+ + val packageName = packageInfo.packageName + + Log.d("App", "版本名称: $versionName") + Log.d("App", "版本代码: $versionCode") + Log.d("App", "包名: $packageName") + + } catch (e: PackageManager.NameNotFoundException) { + e.printStackTrace() + } + } +} +``` + +--- + +## 总结 + +系统API提供了访问Android系统功能和信息的能力: + +1. **系统服务API**:ActivityManager、WindowManager、NotificationManager等 +2. **系统权限API**:权限检查、申请和处理 +3. **系统功能API**:文件系统、网络、传感器等 +4. **系统版本API**:获取系统和应用版本信息 + +使用系统API时需要注意: +- 申请必要的权限 +- 检查系统版本兼容性 +- 正确处理生命周期 +- 及时释放资源 + +通过合理使用系统API,可以构建功能强大的Android应用。 diff --git a/docs/Google开发文档体系/最佳实践/应用架构最佳实践.md b/docs/Google开发文档体系/最佳实践/应用架构最佳实践.md index fd983f8..ea472b5 100644 --- a/docs/Google开发文档体系/最佳实践/应用架构最佳实践.md +++ b/docs/Google开发文档体系/最佳实践/应用架构最佳实践.md @@ -1,9 +1,786 @@ # 应用架构最佳实践 -## 待补充内容 +良好的应用架构是Android应用开发的基础,它直接影响应用的可维护性、可测试性和可扩展性。本文档介绍Android应用架构设计的最佳实践。 -- 架构设计原则 -- 分层架构 -- 模块化设计 -- 依赖管理 -- 架构模式选择 +## 目录 + +- [架构设计原则](#架构设计原则) +- [分层架构](#分层架构) +- [模块化设计](#模块化设计) +- [依赖管理](#依赖管理) +- [架构模式选择](#架构模式选择) +- [Jetpack架构组件](#jetpack架构组件) + +--- + +## 架构设计原则 + +### 1. 关注点分离(Separation of Concerns) + +#### 单一职责原则 + +```kotlin +// ✅ 好的设计:每个类只有一个职责 +class UserRepository { + fun getUser(userId: String): User { + // 只负责数据获取 + } +} + +class UserViewModel : ViewModel() { + private val repository: UserRepository + + fun loadUser(userId: String) { + // 只负责UI逻辑 + viewModelScope.launch { + val user = repository.getUser(userId) + _user.value = user + } + } +} + +// ❌ 不好的设计:一个类承担多个职责 +class UserManager { + fun getUser(userId: String): User { } + fun saveUser(user: User) { } + fun displayUser(user: User) { } // UI逻辑不应该在这里 + fun validateUser(user: User) { } // 业务逻辑不应该在这里 +} +``` + +### 2. 依赖倒置原则(Dependency Inversion) + +#### 依赖接口而非实现 + +```kotlin +// ✅ 好的设计:依赖接口 +interface UserRepository { + suspend fun getUser(userId: String): User +} + +class UserRepositoryImpl( + private val apiService: ApiService, + private val localDataSource: UserLocalDataSource +) : UserRepository { + override suspend fun getUser(userId: String): User { + // 实现细节 + } +} + +class UserViewModel( + private val repository: UserRepository // 依赖接口 +) : ViewModel() { + // ... +} + +// ❌ 不好的设计:依赖具体实现 +class UserViewModel( + private val repository: UserRepositoryImpl // 依赖具体实现 +) : ViewModel() +``` + +### 3. 开闭原则(Open/Closed Principle) + +#### 对扩展开放,对修改关闭 + +```kotlin +// ✅ 好的设计:通过扩展添加功能 +abstract class DataSource { + abstract suspend fun getData(): Data +} + +class RemoteDataSource : DataSource() { + override suspend fun getData(): Data { + // 从远程获取数据 + } +} + +class LocalDataSource : DataSource() { + override suspend fun getData(): Data { + // 从本地获取数据 + } +} + +// 可以添加新的数据源而不修改现有代码 +class CacheDataSource : DataSource() { + override suspend fun getData(): Data { + // 从缓存获取数据 + } +} +``` + +### 4. 接口隔离原则(Interface Segregation) + +#### 使用小而专的接口 + +```kotlin +// ✅ 好的设计:小而专的接口 +interface Readable { + fun read(): String +} + +interface Writable { + fun write(data: String) +} + +class FileManager : Readable, Writable { + override fun read(): String { } + override fun write(data: String) { } +} + +// ❌ 不好的设计:大而全的接口 +interface DataManager { + fun read(): String + fun write(data: String) + fun delete() + fun update() + fun search() + // 太多方法,违反接口隔离原则 +} +``` + +--- + +## 分层架构 + +### 1. 三层架构 + +#### 表现层(Presentation Layer) + +```kotlin +// UI层:Activity/Fragment +class UserActivity : AppCompatActivity() { + private lateinit var viewModel: UserViewModel + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_user) + + viewModel = ViewModelProvider(this)[UserViewModel::class.java] + + viewModel.user.observe(this) { user -> + // 更新UI + updateUI(user) + } + + viewModel.loadUser(userId) + } +} + +// ViewModel:处理UI逻辑 +class UserViewModel( + private val getUserUseCase: GetUserUseCase +) : ViewModel() { + private val _user = MutableLiveData() + val user: LiveData = _user + + fun loadUser(userId: String) { + viewModelScope.launch { + try { + val user = getUserUseCase(userId) + _user.value = user + } catch (e: Exception) { + // 处理错误 + } + } + } +} +``` + +#### 领域层(Domain Layer) + +```kotlin +// UseCase:业务逻辑 +class GetUserUseCase( + private val repository: UserRepository +) { + suspend operator fun invoke(userId: String): Result { + return try { + val user = repository.getUser(userId) + Result.success(user) + } catch (e: Exception) { + Result.failure(e) + } + } +} + +// Entity:领域实体 +data class User( + val id: String, + val name: String, + val email: String +) + +// Repository接口:定义数据访问接口 +interface UserRepository { + suspend fun getUser(userId: String): User +} +``` + +#### 数据层(Data Layer) + +```kotlin +// Repository实现 +class UserRepositoryImpl( + private val remoteDataSource: UserRemoteDataSource, + private val localDataSource: UserLocalDataSource +) : UserRepository { + override suspend fun getUser(userId: String): User { + return try { + // 先尝试从远程获取 + val user = remoteDataSource.getUser(userId) + // 保存到本地 + localDataSource.saveUser(user) + user + } catch (e: Exception) { + // 如果远程失败,从本地获取 + localDataSource.getUser(userId) + } + } +} + +// 远程数据源 +class UserRemoteDataSource( + private val apiService: ApiService +) { + suspend fun getUser(userId: String): User { + return apiService.getUser(userId).toDomain() + } +} + +// 本地数据源 +class UserLocalDataSource( + private val userDao: UserDao +) { + suspend fun getUser(userId: String): User { + return userDao.getUser(userId).toDomain() + } + + suspend fun saveUser(user: User) { + userDao.insertUser(user.toEntity()) + } +} +``` + +### 2. Clean Architecture + +#### 依赖规则 + +``` +表现层 → 领域层 ← 数据层 +``` + +```kotlin +// 领域层不依赖任何其他层 +// Domain Layer +interface UserRepository { + suspend fun getUser(userId: String): User +} + +class GetUserUseCase( + private val repository: UserRepository // 依赖接口 +) { + suspend operator fun invoke(userId: String): User { + return repository.getUser(userId) + } +} + +// 数据层实现领域层的接口 +// Data Layer +class UserRepositoryImpl : UserRepository { + override suspend fun getUser(userId: String): User { + // 实现 + } +} + +// 表现层依赖领域层 +// Presentation Layer +class UserViewModel( + private val getUserUseCase: GetUserUseCase // 依赖UseCase +) : ViewModel() +``` + +--- + +## 模块化设计 + +### 1. 功能模块化 + +#### 模块结构 + +``` +app/ +├── app/ # 主模块 +├── core/ # 核心模块(通用功能) +│ ├── core-common/ +│ ├── core-network/ +│ └── core-database/ +├── feature/ # 功能模块 +│ ├── feature-home/ +│ ├── feature-user/ +│ └── feature-settings/ +└── buildSrc/ # 构建脚本 +``` + +#### 模块依赖关系 + +```gradle +// app/build.gradle +dependencies { + implementation project(':core:core-common') + implementation project(':core:core-network') + implementation project(':feature:feature-home') + implementation project(':feature:feature-user') +} + +// feature-home/build.gradle +dependencies { + implementation project(':core:core-common') + // feature模块不依赖其他feature模块 +} +``` + +### 2. 组件化架构 + +#### 组件通信 + +```kotlin +// 使用接口定义组件通信 +interface HomeNavigation { + fun navigateToUserDetail(userId: String) + fun navigateToSettings() +} + +// Home模块实现 +class HomeFragment : Fragment(), HomeNavigation { + override fun navigateToUserDetail(userId: String) { + findNavController().navigate( + HomeFragmentDirections.actionToUserDetail(userId) + ) + } +} + +// 使用Router进行模块间通信 +class AppRouter { + fun navigateToUserDetail(context: Context, userId: String) { + val intent = Intent(context, UserDetailActivity::class.java) + intent.putExtra("user_id", userId) + context.startActivity(intent) + } +} +``` + +--- + +## 依赖管理 + +### 1. 依赖注入 + +#### 使用Hilt/Dagger + +```kotlin +// 定义Module +@Module +@InstallIn(SingletonComponent::class) +object AppModule { + @Provides + @Singleton + fun provideApiService(): ApiService { + return Retrofit.Builder() + .baseUrl("https://api.example.com/") + .build() + .create(ApiService::class.java) + } + + @Provides + @Singleton + fun provideUserRepository( + apiService: ApiService + ): UserRepository { + return UserRepositoryImpl(apiService) + } +} + +// 注入依赖 +@AndroidEntryPoint +class UserActivity : AppCompatActivity() { + @Inject + lateinit var userRepository: UserRepository + + // ... +} +``` + +#### 手动依赖注入 + +```kotlin +// 依赖容器 +class AppContainer { + private val apiService: ApiService by lazy { + Retrofit.Builder() + .baseUrl("https://api.example.com/") + .build() + .create(ApiService::class.java) + } + + val userRepository: UserRepository by lazy { + UserRepositoryImpl(apiService) + } +} + +// 在Application中初始化 +class MyApplication : Application() { + val appContainer = AppContainer() +} + +// 在Activity中使用 +class UserActivity : AppCompatActivity() { + private lateinit var userRepository: UserRepository + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + userRepository = (application as MyApplication) + .appContainer.userRepository + } +} +``` + +### 2. 依赖版本管理 + +#### 统一版本管理 + +```gradle +// buildSrc/src/main/kotlin/Dependencies.kt +object Versions { + const val kotlin = "1.9.0" + const val androidxCore = "1.9.0" + const val androidxAppCompat = "1.6.1" + const val material = "1.8.0" + const val hilt = "2.44" +} + +object Dependencies { + const val kotlinStdlib = "org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}" + const val androidxCoreKtx = "androidx.core:core-ktx:${Versions.androidxCore}" + const val androidxAppCompat = "androidx.appcompat:appcompat:${Versions.androidxAppCompat}" + const val material = "com.google.android.material:material:${Versions.material}" + const val hiltAndroid = "com.google.dagger:hilt-android:${Versions.hilt}" +} + +// 在模块中使用 +dependencies { + implementation(Dependencies.kotlinStdlib) + implementation(Dependencies.androidxCoreKtx) + implementation(Dependencies.androidxAppCompat) + implementation(Dependencies.material) +} +``` + +--- + +## 架构模式选择 + +### 1. MVVM模式 + +#### MVVM实现 + +```kotlin +// Model:数据模型 +data class User( + val id: String, + val name: String +) + +// ViewModel:UI逻辑 +class UserViewModel( + private val repository: UserRepository +) : ViewModel() { + private val _user = MutableLiveData() + val user: LiveData = _user + + private val _loading = MutableLiveData() + val loading: LiveData = _loading + + fun loadUser(userId: String) { + viewModelScope.launch { + _loading.value = true + try { + val user = repository.getUser(userId) + _user.value = user + } catch (e: Exception) { + // 处理错误 + } finally { + _loading.value = false + } + } + } +} + +// View:UI +class UserActivity : AppCompatActivity() { + private lateinit var viewModel: UserViewModel + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_user) + + viewModel = ViewModelProvider(this)[UserViewModel::class.java] + + viewModel.user.observe(this) { user -> + // 更新UI + nameTextView.text = user.name + } + + viewModel.loading.observe(this) { isLoading -> + progressBar.visibility = if (isLoading) View.VISIBLE else View.GONE + } + } +} +``` + +### 2. MVI模式 + +#### MVI实现 + +```kotlin +// State:UI状态 +data class UserState( + val user: User? = null, + val isLoading: Boolean = false, + val error: String? = null +) + +// Intent:用户意图 +sealed class UserIntent { + object LoadUser : UserIntent() + data class RefreshUser(val userId: String) : UserIntent() +} + +// ViewModel +class UserViewModel( + private val repository: UserRepository +) : ViewModel() { + private val _state = MutableStateFlow(UserState()) + val state: StateFlow = _state.asStateFlow() + + fun handleIntent(intent: UserIntent) { + when (intent) { + is UserIntent.LoadUser -> loadUser() + is UserIntent.RefreshUser -> refreshUser(intent.userId) + } + } + + private fun loadUser() { + viewModelScope.launch { + _state.value = _state.value.copy(isLoading = true) + try { + val user = repository.getUser() + _state.value = _state.value.copy( + user = user, + isLoading = false + ) + } catch (e: Exception) { + _state.value = _state.value.copy( + error = e.message, + isLoading = false + ) + } + } + } +} +``` + +### 3. Clean Architecture + MVVM + +#### 组合使用 + +```kotlin +// Domain Layer +interface UserRepository { + suspend fun getUser(userId: String): User +} + +class GetUserUseCase( + private val repository: UserRepository +) { + suspend operator fun invoke(userId: String): Result { + return try { + Result.success(repository.getUser(userId)) + } catch (e: Exception) { + Result.failure(e) + } + } +} + +// Presentation Layer (MVVM) +class UserViewModel( + private val getUserUseCase: GetUserUseCase +) : ViewModel() { + private val _user = MutableLiveData() + val user: LiveData = _user + + fun loadUser(userId: String) { + viewModelScope.launch { + when (val result = getUserUseCase(userId)) { + is Result.Success -> _user.value = result.data + is Result.Failure -> { + // 处理错误 + } + } + } + } +} +``` + +--- + +## Jetpack架构组件 + +### 1. ViewModel + +#### 使用ViewModel + +```kotlin +class UserViewModel( + private val repository: UserRepository +) : ViewModel() { + private val _user = MutableLiveData() + val user: LiveData = _user + + init { + loadUser() + } + + private fun loadUser() { + viewModelScope.launch { + val user = repository.getUser() + _user.value = user + } + } + + override fun onCleared() { + super.onCleared() + // 清理资源 + } +} +``` + +### 2. LiveData + +#### 使用LiveData + +```kotlin +class UserViewModel : ViewModel() { + private val _user = MutableLiveData() + val user: LiveData = _user + + private val _error = MutableLiveData() + val error: LiveData = _error + + fun loadUser() { + viewModelScope.launch { + try { + val user = repository.getUser() + _user.value = user + _error.value = null + } catch (e: Exception) { + _error.value = e.message + } + } + } +} + +// 在Activity中观察 +viewModel.user.observe(this) { user -> + // 更新UI +} + +viewModel.error.observe(this) { error -> + error?.let { + // 显示错误 + } +} +``` + +### 3. Room数据库 + +#### 使用Room + +```kotlin +// Entity +@Entity(tableName = "users") +data class UserEntity( + @PrimaryKey val id: String, + val name: String, + val email: String +) + +// DAO +@Dao +interface UserDao { + @Query("SELECT * FROM users WHERE id = :userId") + suspend fun getUser(userId: String): UserEntity? + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertUser(user: UserEntity) + + @Delete + suspend fun deleteUser(user: UserEntity) +} + +// Database +@Database(entities = [UserEntity::class], version = 1) +abstract class AppDatabase : RoomDatabase() { + abstract fun userDao(): UserDao +} +``` + +### 4. WorkManager + +#### 使用WorkManager + +```kotlin +// 定义Worker +class SyncWorker( + context: Context, + params: WorkerParameters +) : CoroutineWorker(context, params) { + override suspend fun doWork(): Result { + return try { + // 执行后台任务 + syncData() + Result.success() + } catch (e: Exception) { + Result.retry() + } + } +} + +// 调度任务 +val syncRequest = OneTimeWorkRequestBuilder() + .setConstraints( + Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build() + ) + .build() + +WorkManager.getInstance(context).enqueue(syncRequest) +``` + +--- + +## 总结 + +良好的应用架构应该遵循以下原则: + +1. **关注点分离**:每个组件只负责一个职责 +2. **依赖倒置**:依赖接口而非实现 +3. **分层架构**:清晰的分层结构,便于维护和测试 +4. **模块化设计**:功能模块化,提高可复用性 +5. **依赖管理**:使用依赖注入,管理依赖关系 +6. **架构模式**:根据项目需求选择合适的架构模式 +7. **Jetpack组件**:充分利用Jetpack架构组件 + +通过遵循这些最佳实践,可以构建出高质量、可维护、可扩展的Android应用。 diff --git a/docs/Google开发文档体系/最佳实践/性能优化最佳实践.md b/docs/Google开发文档体系/最佳实践/性能优化最佳实践.md index 0812e02..2448994 100644 --- a/docs/Google开发文档体系/最佳实践/性能优化最佳实践.md +++ b/docs/Google开发文档体系/最佳实践/性能优化最佳实践.md @@ -1,10 +1,716 @@ # 性能优化最佳实践 -## 待补充内容 +性能优化是Android应用开发的重要环节,直接影响用户体验和应用质量。本文档介绍Android应用性能优化的最佳实践。 -- 性能优化策略 -- 启动优化实践 -- 内存优化实践 -- 布局优化实践 -- 网络优化实践 -- 性能监控 +## 目录 + +- [性能优化策略](#性能优化策略) +- [启动优化实践](#启动优化实践) +- [内存优化实践](#内存优化实践) +- [布局优化实践](#布局优化实践) +- [网络优化实践](#网络优化实践) +- [性能监控](#性能监控) + +--- + +## 性能优化策略 + +### 1. 性能优化原则 + +#### 测量优先 + +```kotlin +// ✅ 好的做法:先测量,再优化 +class PerformanceMonitor { + fun measureTime(block: () -> Unit): Long { + val startTime = System.currentTimeMillis() + block() + return System.currentTimeMillis() - startTime + } + + fun measureMemory(block: () -> Unit): Long { + val runtime = Runtime.getRuntime() + val beforeMemory = runtime.totalMemory() - runtime.freeMemory() + block() + val afterMemory = runtime.totalMemory() - runtime.freeMemory() + return afterMemory - beforeMemory + } +} + +// 使用 +val monitor = PerformanceMonitor() +val time = monitor.measureTime { + // 执行代码 +} +Log.d("Performance", "执行时间: ${time}ms") +``` + +#### 优化关键路径 + +```kotlin +// 识别关键路径并优化 +class AppInitializer { + fun initialize() { + // 关键路径:必须立即初始化 + initCriticalComponents() + + // 非关键路径:可以延迟初始化 + Handler(Looper.getMainLooper()).postDelayed({ + initNonCriticalComponents() + }, 100) + } +} +``` + +### 2. 性能指标 + +#### 关键指标 + +```kotlin +// 启动时间 +class StartupTimeTracker { + private var appStartTime: Long = 0 + + fun onAppStart() { + appStartTime = System.currentTimeMillis() + } + + fun onFirstFrame() { + val startupTime = System.currentTimeMillis() - appStartTime + Log.d("Performance", "启动时间: ${startupTime}ms") + } +} + +// 内存使用 +class MemoryTracker { + fun getMemoryUsage(): MemoryInfo { + val runtime = Runtime.getRuntime() + val totalMemory = runtime.totalMemory() + val freeMemory = runtime.freeMemory() + val usedMemory = totalMemory - freeMemory + + return MemoryInfo( + total = totalMemory, + used = usedMemory, + free = freeMemory + ) + } +} +``` + +--- + +## 启动优化实践 + +### 1. Application优化 + +#### 延迟初始化 + +```kotlin +// ✅ 好的做法:延迟初始化非关键组件 +class MyApplication : Application() { + override fun onCreate() { + super.onCreate() + + // 关键初始化:必须立即执行 + initCriticalComponents() + + // 非关键初始化:延迟执行 + initNonCriticalComponentsAsync() + } + + private fun initCriticalComponents() { + // 初始化关键组件 + CrashReporting.init(this) + } + + private fun initNonCriticalComponentsAsync() { + // 使用后台线程初始化 + Thread { + // 初始化非关键组件 + Analytics.init(this) + ImageLoader.init(this) + }.start() + } +} +``` + +#### 使用App Startup + +```kotlin +// 使用App Startup统一管理初始化 +class MyInitializer : Initializer { + override fun create(context: Context) { + // 初始化组件 + Analytics.init(context) + } + + override fun dependencies(): List>> { + // 定义依赖关系 + return listOf(OtherInitializer::class.java) + } +} + +// 在AndroidManifest.xml中注册 +// +// +// +``` + +### 2. 首屏优化 + +#### 减少首屏布局复杂度 + +```xml + + + + + + + + +``` + +#### 使用ViewStub延迟加载 + +```xml + + +``` + +```kotlin +// 在需要时加载 +class MainActivity : AppCompatActivity() { + private lateinit var viewStub: ViewStub + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + viewStub = findViewById(R.id.viewStub) + + // 延迟加载 + button.setOnClickListener { + if (viewStub.parent != null) { + viewStub.inflate() + } + } + } +} +``` + +### 3. 启动时间测量 + +#### 使用Trace API + +```kotlin +// 使用Trace API标记启动流程 +class MainActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + Trace.beginSection("MainActivity.onCreate") + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + Trace.beginSection("initViews") + initViews() + Trace.endSection() + + Trace.beginSection("loadData") + loadData() + Trace.endSection() + + Trace.endSection() + } +} + +// 使用Systrace分析 +// python systrace.py -t 10 -o trace.html sched freq idle am wm gfx view binder_driver hal dalvik camera input res +``` + +--- + +## 内存优化实践 + +### 1. 内存泄漏预防 + +#### 避免静态引用 + +```kotlin +// ❌ 不好的做法:静态引用Context +object AppContext { + var context: Context? = null // 可能导致内存泄漏 +} + +// ✅ 好的做法:使用Application Context +object AppContext { + fun getContext(): Context { + return MyApplication.instance + } +} +``` + +#### 正确处理生命周期 + +```kotlin +// ✅ 好的做法:正确处理生命周期 +class MainActivity : AppCompatActivity() { + private var handler: Handler? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + // 使用静态内部类+WeakReference + handler = MyHandler(this) + } + + override fun onDestroy() { + super.onDestroy() + handler?.removeCallbacksAndMessages(null) + handler = null + } + + private class MyHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + private val activityRef = WeakReference(activity) + + override fun handleMessage(msg: Message) { + activityRef.get()?.let { + // 处理消息 + } + } + } +} +``` + +### 2. 内存使用优化 + +#### 使用对象池 + +```kotlin +// 对象池:复用对象,减少GC +class ObjectPool(private val factory: () -> T, private val maxSize: Int = 10) { + private val pool = mutableListOf() + + fun acquire(): T { + return if (pool.isNotEmpty()) { + pool.removeAt(pool.size - 1) + } else { + factory() + } + } + + fun release(obj: T) { + if (pool.size < maxSize) { + pool.add(obj) + } + } +} + +// 使用 +val viewPool = ObjectPool({ View(context) }) +val view = viewPool.acquire() +// 使用view +viewPool.release(view) +``` + +#### 优化图片加载 + +```kotlin +// 使用Glide等图片加载库 +Glide.with(context) + .load(imageUrl) + .placeholder(R.drawable.placeholder) + .error(R.drawable.error) + .override(800, 600) // 指定尺寸 + .into(imageView) + +// 使用WebP格式 +// WebP格式比PNG/JPG更小,加载更快 + +// 使用图片压缩 +fun compressBitmap(bitmap: Bitmap, quality: Int = 80): ByteArray { + val stream = ByteArrayOutputStream() + bitmap.compress(Bitmap.CompressFormat.WEBP, quality, stream) + return stream.toByteArray() +} +``` + +### 3. 内存监控 + +#### 使用LeakCanary + +```gradle +// build.gradle +dependencies { + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12' +} +``` + +```kotlin +// 自动检测内存泄漏 +// LeakCanary会自动检测并报告内存泄漏 +``` + +#### 手动内存分析 + +```kotlin +// 获取内存信息 +class MemoryAnalyzer { + fun getMemoryInfo(): String { + val runtime = Runtime.getRuntime() + val maxMemory = runtime.maxMemory() + val totalMemory = runtime.totalMemory() + val freeMemory = runtime.freeMemory() + val usedMemory = totalMemory - freeMemory + + return """ + Max Memory: ${maxMemory / 1024 / 1024}MB + Total Memory: ${totalMemory / 1024 / 1024}MB + Used Memory: ${usedMemory / 1024 / 1024}MB + Free Memory: ${freeMemory / 1024 / 1024}MB + """.trimIndent() + } + + fun dumpHeap(): File { + val heapDumpFile = File(cacheDir, "heap_dump.hprof") + Debug.dumpHprofData(heapDumpFile.absolutePath) + return heapDumpFile + } +} +``` + +--- + +## 布局优化实践 + +### 1. 减少布局层级 + +#### 使用ConstraintLayout + +```xml + + + + + + + + + + + + + + +``` + +### 2. 避免过度绘制 + +#### 减少背景绘制 + +```xml + + + + + + + + + + + +``` + +#### 使用clipToPadding + +```xml + + +``` + +### 3. RecyclerView优化 + +#### ViewHolder复用 + +```kotlin +// ✅ 好的做法:正确实现ViewHolder +class UserAdapter : RecyclerView.Adapter() { + class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val nameTextView: TextView = itemView.findViewById(R.id.name) + val emailTextView: TextView = itemView.findViewById(R.id.email) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_user, parent, false) + return ViewHolder(view) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val user = users[position] + holder.nameTextView.text = user.name + holder.emailTextView.text = user.email + } +} +``` + +#### 使用DiffUtil + +```kotlin +// 使用DiffUtil优化列表更新 +class UserDiffCallback( + private val oldList: List, + private val newList: List +) : DiffUtil.Callback() { + override fun getOldListSize() = oldList.size + override fun getNewListSize() = newList.size + + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return oldList[oldItemPosition].id == newList[newItemPosition].id + } + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return oldList[oldItemPosition] == newList[newItemPosition] + } +} + +// 使用 +val diffResult = DiffUtil.calculateDiff(UserDiffCallback(oldList, newList)) +adapter.users = newList +diffResult.dispatchUpdatesTo(adapter) +``` + +--- + +## 网络优化实践 + +### 1. 请求优化 + +#### 请求合并 + +```kotlin +// ✅ 好的做法:合并请求 +class ApiService { + @GET("users") + suspend fun getUsers(@Query("ids") ids: String): List + // 一次请求获取多个用户,而不是多次请求 +} + +// ❌ 不好的做法:多次请求 +// for (id in userIds) { +// apiService.getUser(id) +// } +``` + +#### 使用缓存 + +```kotlin +// 使用OkHttp缓存 +val client = OkHttpClient.Builder() + .cache(Cache(cacheDir, 10 * 1024 * 1024)) // 10MB缓存 + .build() + +// 使用Retrofit缓存 +@Headers("Cache-Control: max-age=3600") +@GET("users/{id}") +suspend fun getUser(@Path("id") id: String): User +``` + +### 2. 数据压缩 + +#### 使用Gzip + +```kotlin +// 服务器端启用Gzip压缩 +// 客户端自动处理Gzip响应 +// OkHttp自动支持Gzip解压 +``` + +#### 数据格式优化 + +```kotlin +// 使用Protobuf替代JSON +// Protobuf更小、更快 +data class User( + val id: String, + val name: String, + val email: String +) + +// 转换为Protobuf +val userProto = UserProto.newBuilder() + .setId(user.id) + .setName(user.name) + .setEmail(user.email) + .build() +``` + +### 3. 网络监控 + +#### 监控网络请求 + +```kotlin +// 使用OkHttp Interceptor监控 +class NetworkMonitorInterceptor : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val request = chain.request() + val startTime = System.currentTimeMillis() + + val response = chain.proceed(request) + + val duration = System.currentTimeMillis() - startTime + Log.d("Network", "${request.url} - ${duration}ms") + + return response + } +} + +val client = OkHttpClient.Builder() + .addInterceptor(NetworkMonitorInterceptor()) + .build() +``` + +--- + +## 性能监控 + +### 1. 性能指标收集 + +#### 使用Firebase Performance + +```gradle +// build.gradle +dependencies { + implementation 'com.google.firebase:firebase-perf-ktx:20.4.1' +} +``` + +```kotlin +// 监控自定义性能指标 +val trace = FirebasePerformance.getInstance().newTrace("load_user_data") +trace.start() + +// 执行操作 +loadUserData() + +trace.stop() +``` + +#### 自定义性能监控 + +```kotlin +class PerformanceTracker { + private val metrics = mutableMapOf() + + fun startTrace(name: String) { + metrics[name] = System.currentTimeMillis() + } + + fun endTrace(name: String) { + val startTime = metrics[name] + if (startTime != null) { + val duration = System.currentTimeMillis() - startTime + Log.d("Performance", "$name: ${duration}ms") + metrics.remove(name) + } + } +} + +// 使用 +val tracker = PerformanceTracker() +tracker.startTrace("load_data") +// 执行操作 +tracker.endTrace("load_data") +``` + +### 2. 性能分析工具 + +#### 使用Android Profiler + +```kotlin +// Android Studio Profiler可以监控: +// - CPU使用率 +// - 内存使用情况 +// - 网络请求 +// - 电量消耗 +``` + +#### 使用Systrace + +```bash +# 使用Systrace分析性能 +python systrace.py -t 10 -o trace.html sched freq idle am wm gfx view binder_driver hal dalvik camera input res + +# 在代码中标记 +Trace.beginSection("my_section") +// 执行代码 +Trace.endSection() +``` + +#### 使用Perfetto + +```kotlin +// Perfetto是更强大的性能分析工具 +// 可以分析: +// - CPU调度 +// - 内存分配 +// - 文件I/O +// - 网络活动 +``` + +--- + +## 总结 + +性能优化是一个持续的过程,需要: + +1. **测量优先**:先测量性能,找出瓶颈 +2. **优化关键路径**:优先优化影响用户体验的关键路径 +3. **启动优化**:减少启动时间,提升用户体验 +4. **内存优化**:避免内存泄漏,优化内存使用 +5. **布局优化**:减少布局层级,避免过度绘制 +6. **网络优化**:优化网络请求,使用缓存 +7. **性能监控**:持续监控性能指标,及时发现问题 + +通过遵循这些最佳实践,可以显著提升应用的性能和用户体验。 diff --git a/docs/Google开发文档体系/最佳实践/用户体验最佳实践.md b/docs/Google开发文档体系/最佳实践/用户体验最佳实践.md index 8b3b7b4..583d279 100644 --- a/docs/Google开发文档体系/最佳实践/用户体验最佳实践.md +++ b/docs/Google开发文档体系/最佳实践/用户体验最佳实践.md @@ -1,9 +1,789 @@ # 用户体验最佳实践 -## 待补充内容 +用户体验(UX)是Android应用成功的关键因素。良好的用户体验能够提升用户满意度、增加用户留存率,并提升应用在应用商店的评分。本文档介绍Android应用开发中的用户体验最佳实践。 -- UX设计原则 -- 界面设计 -- 交互设计 -- 可访问性 -- 国际化 +## 目录 + +- [UX设计原则](#ux设计原则) +- [界面设计](#界面设计) +- [交互设计](#交互设计) +- [可访问性](#可访问性) +- [国际化](#国际化) +- [性能与体验](#性能与体验) + +--- + +## UX设计原则 + +### 1. 以用户为中心 + +#### 理解用户需求 + +```kotlin +// 在设计功能前,先理解用户需求 +// 1. 用户画像分析 +// 2. 用户场景分析 +// 3. 用户痛点识别 + +// 示例:电商应用 +// 用户需求:快速找到商品并完成购买 +// 设计要点: +// - 搜索功能突出 +// - 商品信息清晰 +// - 购买流程简化 +``` + +#### 用户反馈机制 + +```kotlin +// 建立用户反馈渠道 +class FeedbackManager { + fun collectUserFeedback(feedback: String) { + // 收集用户反馈 + Analytics.logEvent("user_feedback", mapOf("content" to feedback)) + } + + fun showFeedbackDialog(context: Context) { + // 显示反馈对话框 + MaterialAlertDialogBuilder(context) + .setTitle("反馈建议") + .setView(EditText(context)) + .setPositiveButton("提交") { _, _ -> + collectUserFeedback() + } + .show() + } +} +``` + +### 2. 简洁性原则 + +#### 界面简洁 + +```xml + + + + + + + + + + +``` + +#### 操作简化 + +```kotlin +// ✅ 好的设计:简化操作流程 +class CheckoutActivity : AppCompatActivity() { + fun proceedToPayment() { + // 一键支付,减少步骤 + if (validateOrder()) { + startActivity(Intent(this, PaymentActivity::class.java)) + } + } +} + +// ❌ 不好的设计:操作步骤过多 +// 避免让用户进行过多步骤才能完成操作 +``` + +### 3. 一致性原则 + +#### 视觉一致性 + +```kotlin +// 使用统一的主题和样式 +// styles.xml + +``` + +#### 交互一致性 + +```kotlin +// 统一的交互模式 +class NavigationHelper { + companion object { + // 统一的导航方式 + fun navigateToDetail(context: Context, itemId: String) { + val intent = Intent(context, DetailActivity::class.java) + intent.putExtra("item_id", itemId) + context.startActivity(intent) + } + + // 统一的返回方式 + fun handleBackPress(activity: Activity): Boolean { + if (activity.supportFragmentManager.backStackEntryCount > 0) { + activity.supportFragmentManager.popBackStack() + return true + } + return false + } + } +} +``` + +### 4. 反馈原则 + +#### 操作反馈 + +```kotlin +// 用户操作后提供即时反馈 +class UserFeedbackHelper { + fun showLoading(context: Context) { + // 显示加载状态 + ProgressDialog.show(context, "加载中", "请稍候...") + } + + fun showSuccess(context: Context, message: String) { + // 显示成功提示 + Snackbar.make( + findViewById(android.R.id.content), + message, + Snackbar.LENGTH_SHORT + ).show() + } + + fun showError(context: Context, message: String) { + // 显示错误提示 + MaterialAlertDialogBuilder(context) + .setTitle("错误") + .setMessage(message) + .setPositiveButton("确定", null) + .show() + } +} +``` + +#### 状态反馈 + +```kotlin +// 使用状态指示器 +class StatusIndicator { + fun showStatus(view: View, status: Status) { + when (status) { + Status.LOADING -> { + view.alpha = 0.5f + view.isEnabled = false + } + Status.SUCCESS -> { + view.alpha = 1.0f + view.isEnabled = true + } + Status.ERROR -> { + view.alpha = 0.5f + view.isEnabled = false + } + } + } +} +``` + +--- + +## 界面设计 + +### 1. Material Design + +#### Material Design组件 + +```xml + + + + + + + + + + +``` + +#### Material主题 + +```xml + + + + +``` + +### 2. 响应式设计 + +#### 多屏幕适配 + +```xml + + + + + + + +``` + +#### 横竖屏适配 + +```kotlin +// 横竖屏布局适配 +class MainActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + // 根据屏幕方向加载不同布局 + val layoutRes = if (isLandscape()) { + R.layout.activity_main_landscape + } else { + R.layout.activity_main_portrait + } + + setContentView(layoutRes) + } + + private fun isLandscape(): Boolean { + return resources.configuration.orientation == + Configuration.ORIENTATION_LANDSCAPE + } +} +``` + +### 3. 布局优化 + +#### 减少布局层级 + +```xml + + + + + + + + + + + + + +``` + +#### 使用ViewStub延迟加载 + +```xml + + +``` + +```kotlin +// 在需要时加载ViewStub +class MainActivity : AppCompatActivity() { + private lateinit var viewStub: ViewStub + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + viewStub = findViewById(R.id.viewStub) + + // 延迟加载 + button.setOnClickListener { + if (viewStub.parent != null) { + viewStub.inflate() + } + } + } +} +``` + +--- + +## 交互设计 + +### 1. 导航设计 + +#### 底部导航 + +```xml + + +``` + +```kotlin +// 处理底部导航点击 +bottomNavigation.setOnItemSelectedListener { item -> + when (item.itemId) { + R.id.nav_home -> { + // 导航到首页 + navigateToHome() + true + } + R.id.nav_search -> { + // 导航到搜索 + navigateToSearch() + true + } + R.id.nav_profile -> { + // 导航到个人中心 + navigateToProfile() + true + } + else -> false + } +} +``` + +#### 导航组件 + +```kotlin +// 使用Navigation Component +class MainActivity : AppCompatActivity() { + private lateinit var navController: NavController + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + val navHostFragment = supportFragmentManager + .findFragmentById(R.id.nav_host_fragment) as NavHostFragment + navController = navHostFragment.navController + + // 设置导航监听 + navController.addOnDestinationChangedListener { _, destination, _ -> + // 根据目标更新UI + updateUI(destination.id) + } + } +} +``` + +### 2. 手势交互 + +#### 滑动操作 + +```kotlin +// 实现滑动删除 +class SwipeToDeleteCallback( + private val adapter: RecyclerView.Adapter<*> +) : ItemTouchHelper.SimpleCallback( + 0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT +) { + override fun onMove( + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + target: RecyclerView.ViewHolder + ): Boolean = false + + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { + val position = viewHolder.adapterPosition + // 删除项 + adapter.notifyItemRemoved(position) + } +} + +// 使用 +val itemTouchHelper = ItemTouchHelper(SwipeToDeleteCallback(adapter)) +itemTouchHelper.attachToRecyclerView(recyclerView) +``` + +#### 点击反馈 + +```kotlin +// 使用Ripple效果提供点击反馈 +