1. 为什么Activity是Android开发的基石?
Activity作为Android四大组件之首,其重要性怎么强调都不为过。我在2013年开发第一个Android应用时,就曾因为对Activity生命周期理解不透彻,导致用户切换应用时数据丢失的严重事故。现在回想起来,这些教训反而成了最宝贵的经验。
Activity本质上是一个包含用户界面的组件,它就像餐厅里的服务员:
- 负责与顾客(用户)直接交互
- 管理餐桌(界面)的布置和清理
- 协调后厨(后台服务)的工作
- 处理突发情况(配置变更)
在Android Studio中新建一个Basic Activity模板项目,会自动生成以下关键文件:
code复制app/
├── java/
│ └── com.example.myapp/
│ ├── MainActivity.kt
│ └── ...
├── res/
│ ├── layout/
│ │ └── activity_main.xml
│ └── values/
│ └── themes.xml
└── AndroidManifest.xml
提示:Android Studio 2023.2版本开始,新建Activity默认使用ViewBinding替代findViewById,这是Google推荐的做法,能有效避免空指针异常。
2. Activity生命周期的深度解析
2.1 生命周期回调的实战意义
官方文档中的生命周期图示往往让人困惑,我更喜欢用现实场景来比喻:
-
onCreate():就像餐厅开业前的准备
- 必须调用super.onCreate()
- 初始化基本组件
- 加载布局(setContentView)
- 示例代码:
kotlin复制override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) // 恢复保存的状态 savedInstanceState?.getString("key")?.let { // 处理恢复数据 } }
-
onStart():开门迎客前的最后检查
- 适合启动与UI相关的资源
- 比如注册广播接收器
-
onResume():顾客正在点餐
- 应用最活跃的状态
- 启动动画、摄像头预览等
2.2 容易被忽视的onSaveInstanceState
这是新手最容易犯错的地方。当系统需要回收Activity时(如内存不足),会调用此方法保存临时状态:
kotlin复制override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("editTextValue", binding.editText.text.toString())
}
但要注意:
- 不适合保存大量数据(超过50KB可能被系统丢弃)
- 不会在用户主动退出时调用
- 应该与ViewModel配合使用
3. Activity间通信的进阶技巧
3.1 启动Activity的正确姿势
从MainActivity跳转到DetailActivity时,传统方式是:
kotlin复制val intent = Intent(this, DetailActivity::class.java).apply {
putExtra("item_id", 123)
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}
startActivity(intent)
但更现代的做法是使用Activity Result API:
kotlin复制// 在onCreate中注册
val getResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
val data = result.data?.getStringExtra("result")
// 处理返回数据
}
}
// 启动Activity
getResult.launch(Intent(this, DetailActivity::class.java))
3.2 共享元素转场动画
让界面跳转更流畅的秘密:
- 在res/transition/创建过渡动画XML
- 在布局文件中为View添加transitionName
- 启动时配置:
kotlin复制val options = ActivityOptions.makeSceneTransitionAnimation(
this,
Pair(binding.imageView, "shared_image")
)
startActivity(intent, options.toBundle())
4. 现代Android开发中的Activity最佳实践
4.1 与Jetpack组件的协作
ViewModel + LiveData的黄金组合:
kotlin复制class MainActivity : AppCompatActivity() {
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.userData.observe(this) { user ->
// 更新UI
}
}
}
4.2 处理深链接(Deep Link)
在AndroidManifest.xml中配置:
xml复制<activity android:name=".DetailActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="https"
android:host="example.com"
android:pathPrefix="/detail"/>
</intent-filter>
</activity>
在Activity中处理:
kotlin复制val uri = intent.data
uri?.pathSegments?.get(1)?.let { itemId ->
// 加载对应内容
}
4.3 多窗口模式适配
从Android 7.0开始需要处理:
kotlin复制override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean) {
super.onMultiWindowModeChanged(isInMultiWindowMode)
if (isInMultiWindowMode) {
// 调整UI布局
}
}
5. 调试与性能优化实战
5.1 内存泄漏检测
在build.gradle中添加LeakCanary:
gradle复制dependencies {
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'
}
常见泄漏场景:
- 非静态内部类持有Activity引用
- 未取消的Handler/Runnable
- 单例模式误用
5.2 启动时间优化
使用ADB测量冷启动时间:
bash复制adb shell am start-activity -W -n com.example/.MainActivity
优化建议:
- 减少onCreate中的耗时操作
- 使用SplashScreen API
- 延迟初始化非关键组件
我在实际项目中通过以下配置将启动时间缩短了40%:
kotlin复制// 在Application类中
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
setupStrictMode()
}
private fun setupStrictMode() {
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.penaltyLog()
.build()
)
}
}
6. 兼容性问题的解决之道
6.1 处理权限变更
Android 13的运行时权限变化:
kotlin复制when {
ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED -> {
// 已有权限
}
shouldShowRequestPermissionRationale(permission) -> {
// 显示解释对话框
}
else -> {
requestPermissions(arrayOf(permission), REQUEST_CODE)
}
}
6.2 适配不同屏幕尺寸
创建不同资源目录:
code复制res/
├── layout/
├── layout-sw600dp/ // 7寸平板
└── layout-sw720dp/ // 10寸平板
在代码中动态判断:
kotlin复制val isTablet = resources.configuration.smallestScreenWidthDp >= 600
7. 未来趋势:Compose与Activity的融合
虽然Jetpack Compose正在改变UI开发方式,但Activity仍然是入口点:
kotlin复制class ComposeActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
Surface {
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
关键整合点:
- 在Activity中使用ComposeView嵌入传统视图
- 通过rememberSaveable保持状态
- 处理返回按钮导航
我在实际项目中发现,混合使用传统XML布局和Compose时,需要注意:
- ComposeView的性能开销
- 主题样式的统一管理
- 导航栈的协调处理
