概述
Activity是Android应用的核心组件之一,代表一个用户界面。每个Activity都是一个独立的屏幕,用户可以与之交互。理解Activity的生命周期和组件通信机制是Android开发的基础。
学习目标
- 掌握Activity完整生命周期
- 理解Activity的启动模式
- 熟练使用Intent进行组件通信
- 掌握数据传递的各种方式
- 了解Jetpack Navigation组件
- 掌握Activity性能优化技巧
Activity基础
Activity是什么?
Activity是Android四大组件之一,提供了一个用户可以交互的屏幕。每个Activity都是android.app.Activity类的子类。
// Java实现
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
// Kotlin实现
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
在清单文件中注册
每个Activity都必须在AndroidManifest.xml中注册:
<manifest ...>
<application ...>
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.MyApp">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:exported="false"
android:parentActivityName=".MainActivity" />
</application>
</manifest>
生命周期详解
生命周期方法
Activity的生命周期由一系列的回调方法组成,这些方法在Activity的不同状态之间转换时被调用。
完整生命周期流程图
[启动Activity]
↓
onCreate() ← 创建Activity
↓
onStart() ← Activity即将可见
↓
onResume() ← Activity获得焦点,可交互
↓
[Activity运行中]
↓
onPause() ← Activity失去焦点
↓
onStop() ← Activity不可见
↓
onDestroy() ← Activity销毁
↓
[Activity结束]
生命周期状态详解
| 状态 | 描述 | 特点 |
|---|---|---|
| 创建(Created) | Activity被创建但不可见 | 执行初始化操作 |
| 启动(Started) | Activity可见但不在前台 | 用户可以看到界面 |
| 恢复(Resumed) | Activity在前台且可交互 | 用户可以操作 |
| 暂停(Paused) | Activity部分可见 | 失去焦点但仍可见 |
| 停止(Stopped) | Activity完全不可见 | 被其他Activity覆盖 |
| 销毁(Destroyed) | Activity被销毁 | 释放所有资源 |
生命周期方法实现
// Java完整实现
public class LifecycleActivity extends AppCompatActivity {
private static final String TAG = "LifecycleActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate: Activity创建");
setContentView(R.layout.activity_lifecycle);
// 恢复保存的状态
if (savedInstanceState != null) {
String data = savedInstanceState.getString("key");
Log.d(TAG, "onCreate: 恢复数据 - " + data);
}
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart: Activity即将可见");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume: Activity获得焦点");
// 恢复暂停的操作,如动画、传感器等
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause: Activity失去焦点");
// 暂停操作,如动画、传感器等
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop: Activity不可见");
// 停止耗时操作
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, "onRestart: Activity重新启动");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: Activity销毁");
// 释放资源
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, "onSaveInstanceState: 保存状态");
outState.putString("key", "需要保存的数据");
}
}
// Kotlin实现
class LifecycleActivity : AppCompatActivity() {
companion object {
private const val TAG = "LifecycleActivity"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "onCreate: Activity创建")
setContentView(R.layout.activity_lifecycle)
// 恢复保存的状态
savedInstanceState?.let {
val data = it.getString("key")
Log.d(TAG, "onCreate: 恢复数据 - $data")
}
}
override fun onStart() {
super.onStart()
Log.d(TAG, "onStart: Activity即将可见")
}
override fun onResume() {
super.onResume()
Log.d(TAG, "onResume: Activity获得焦点")
}
override fun onPause() {
super.onPause()
Log.d(TAG, "onPause: Activity失去焦点")
}
override fun onStop() {
super.onStop()
Log.d(TAG, "onStop: Activity不可见")
}
override fun onRestart() {
super.onRestart()
Log.d(TAG, "onRestart: Activity重新启动")
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy: Activity销毁")
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
Log.d(TAG, "onSaveInstanceState: 保存状态")
outState.putString("key", "需要保存的数据")
}
}
生命周期场景分析
场景1:正常启动和退出
启动:onCreate() → onStart() → onResume()
退出:onPause() → onStop() → onDestroy()
场景2:被其他Activity覆盖
被覆盖:onPause() → onStop()
返回:onRestart() → onStart() → onResume()
场景3:屏幕旋转
旋转前:onPause() → onStop() → onSaveInstanceState() → onDestroy()
旋转后:onCreate() → onStart() → onRestoreInstanceState() → onResume()
处理配置变更
防止Activity在配置变更时重建:
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize">
</activity>
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Log.d(TAG, "横屏模式");
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
Log.d(TAG, "竖屏模式");
}
}
固定屏幕方向
<!-- 强制竖屏 -->
<activity
android:name=".MainActivity"
android:screenOrientation="portrait" />
<!-- 强制横屏 -->
<activity
android:name=".VideoActivity"
android:screenOrientation="landscape" />
Activity管理
创建Activity
使用Android Studio创建
- 右键点击包名 → New → Activity → Empty Activity
- 输入Activity名称
- 选择是否生成布局文件
- 点击Finish
手动创建Activity
- 创建Activity类:
// Java
public class NewActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new);
}
}
// Kotlin
class NewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_new)
}
}
- 创建布局文件
res/layout/activity_new.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Activity"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- 在AndroidManifest.xml中注册:
<activity
android:name=".NewActivity"
android:exported="false" />
启动Activity
基本启动方式
// Java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.btn_start);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 显式Intent启动Activity
Intent intent = new Intent(MainActivity.this, NewActivity.class);
startActivity(intent);
}
});
}
}
// Kotlin
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.btn_start).setOnClickListener {
// 显式Intent启动Activity
val intent = Intent(this, NewActivity::class.java)
startActivity(intent)
// 添加转场动画
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left)
}
}
}
关闭Activity
// 关闭当前Activity
finish();
// 关闭当前Activity并返回结果
Intent resultIntent = new Intent();
resultIntent.putExtra("result", "success");
setResult(RESULT_OK, resultIntent);
finish();
// 关闭整个应用
finishAffinity(); // API 16+
Activity启动模式
Activity的启动模式决定了Activity的实例如何被创建和复用。
四种启动模式
| 模式 | 说明 | 使用场景 |
|---|---|---|
| standard | 默认模式,每次都创建新实例 | 普通页面 |
| singleTop | 栈顶复用,如果在栈顶则复用 | 通知页面 |
| singleTask | 栈内复用,如果存在则清除其上所有Activity | 主页面 |
| singleInstance | 独立栈,全局唯一实例 | 特殊功能页面 |
设置启动模式
方式1:在AndroidManifest.xml中设置
<activity
android:name=".MainActivity"
android:launchMode="singleTask" />
方式2:通过Intent标志设置
Intent intent = new Intent(this, NewActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
常用的Intent标志:
FLAG_ACTIVITY_NEW_TASK:在新的任务栈中启动FLAG_ACTIVITY_SINGLE_TOP:singleTop效果FLAG_ACTIVITY_CLEAR_TOP:清除栈顶ActivityFLAG_ACTIVITY_CLEAR_TASK:清除整个任务栈
Intent与组件通信
Intent概述
Intent是Android中用于组件之间通信的消息对象。它可以用于:
- 启动Activity
- 启动Service
- 发送广播
- 启动ContentProvider查询
Intent类型
1. 显式Intent
明确指定要启动的组件类名:
// Java
Intent intent = new Intent(this, TargetActivity.class);
startActivity(intent);
// Kotlin
val intent = Intent(this, TargetActivity::class.java)
startActivity(intent)
2. 隐式Intent
不指定具体组件,而是声明要执行的操作:
// 打开网页
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://www.android.com"));
startActivity(intent);
// 拨打电话
Intent callIntent = new Intent(Intent.ACTION_DIAL);
callIntent.setData(Uri.parse("tel:10086"));
startActivity(callIntent);
// 发送邮件
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("text/plain");
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"test@example.com"});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "邮件主题");
emailIntent.putExtra(Intent.EXTRA_TEXT, "邮件内容");
startActivity(Intent.createChooser(emailIntent, "选择邮件应用"));
IntentFilter配置
在AndroidManifest.xml中配置IntentFilter以响应隐式Intent:
<activity android:name=".MyActivity">
<intent-filter>
<action android:name="com.example.ACTION_CUSTOM" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="myapp" android:host="open" />
</intent-filter>
</activity>
使用自定义Action启动:
Intent intent = new Intent("com.example.ACTION_CUSTOM");
intent.setData(Uri.parse("myapp://open"));
startActivity(intent);
Intent常用Action
| Action | 说明 | 示例 |
|---|---|---|
| ACTION_VIEW | 查看数据 | 打开网页、图片 |
| ACTION_EDIT | 编辑数据 | 编辑联系人 |
| ACTION_DIAL | 拨号界面 | 显示拨号界面 |
| ACTION_CALL | 直接拨打电话 | 需要权限 |
| ACTION_SEND | 发送数据 | 分享功能 |
| ACTION_PICK | 选择数据 | 选择图片 |
完整示例:显式和隐式Intent
// 主页面实现
public class IntentDemoActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_demo);
// 显式Intent示例
findViewById(R.id.btn_explicit).setOnClickListener(v -> {
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
});
// 隐式Intent示例
findViewById(R.id.btn_implicit).setOnClickListener(v -> {
Intent intent = new Intent("com.example.ACTION_DEMO");
intent.addCategory(Intent.CATEGORY_DEFAULT);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
} else {
Toast.makeText(this, "没有找到可以处理该Intent的Activity",
Toast.LENGTH_SHORT).show();
}
});
// 系统Intent示例
findViewById(R.id.btn_system).setOnClickListener(v -> {
// 选择图片
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, 100);
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 100 && resultCode == RESULT_OK && data != null) {
Uri imageUri = data.getData();
// 处理选中的图片
}
}
}
PendingIntent
PendingIntent是对Intent的包装,允许外部应用执行Intent:
// 创建通知时使用PendingIntent
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(
this,
0,
notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("通知标题")
.setContentText("通知内容")
.setContentIntent(pendingIntent)
.setAutoCancel(true);
数据传递
传递基本数据类型
使用Intent.putExtra()
// Java - 发送数据
public class MainActivity extends AppCompatActivity {
private void sendData() {
Intent intent = new Intent(this, DetailActivity.class);
// 传递基本数据类型
intent.putExtra("name", "张三");
intent.putExtra("age", 25);
intent.putExtra("isVip", true);
intent.putExtra("score", 98.5f);
// 传递数组
intent.putExtra("hobbies", new String[]{"编程", "读书", "运动"});
startActivity(intent);
}
}
// Java - 接收数据
public class DetailActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
String name = intent.getStringExtra("name");
int age = intent.getIntExtra("age", 0); // 默认值0
boolean isVip = intent.getBooleanExtra("isVip", false);
float score = intent.getFloatExtra("score", 0f);
String[] hobbies = intent.getStringArrayExtra("hobbies");
// 使用接收到的数据
Log.d("DetailActivity", "Name: " + name + ", Age: " + age);
}
}
// Kotlin - 发送数据
class MainActivity : AppCompatActivity() {
private fun sendData() {
val intent = Intent(this, DetailActivity::class.java).apply {
putExtra("name", "张三")
putExtra("age", 25)
putExtra("isVip", true)
putExtra("score", 98.5f)
putExtra("hobbies", arrayOf("编程", "读书", "运动"))
}
startActivity(intent)
}
}
// Kotlin - 接收数据
class DetailActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
intent?.let {
val name = it.getStringExtra("name")
val age = it.getIntExtra("age", 0)
val isVip = it.getBooleanExtra("isVip", false)
val score = it.getFloatExtra("score", 0f)
val hobbies = it.getStringArrayExtra("hobbies")
Log.d("DetailActivity", "Name: $name, Age: $age")
}
}
}
使用Bundle传递数据
Bundle提供了更灵活的数据传递方式:
// Java - 使用Bundle
public class MainActivity extends AppCompatActivity {
private void sendDataWithBundle() {
Intent intent = new Intent(this, DetailActivity.class);
// 创建Bundle
Bundle bundle = new Bundle();
bundle.putString("name", "李四");
bundle.putInt("age", 30);
bundle.putSerializable("date", new Date());
// 传递自定义对象(需要实现Serializable或Parcelable)
User user = new User("王五", 28);
bundle.putSerializable("user", user);
intent.putExtras(bundle);
startActivity(intent);
}
}
// 接收Bundle数据
public class DetailActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
String name = bundle.getString("name");
int age = bundle.getInt("age");
Date date = (Date) bundle.getSerializable("date");
User user = (User) bundle.getSerializable("user");
}
}
}
传递对象
方式1:实现Serializable接口
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
// getter和setter方法
}
方式2:实现Parcelable接口(推荐)
public class Student implements Parcelable {
private String name;
private int age;
private List<String> courses;
public Student(String name, int age) {
this.name = name;
this.age = age;
this.courses = new ArrayList<>();
}
protected Student(Parcel in) {
name = in.readString();
age = in.readInt();
courses = in.createStringArrayList();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
dest.writeStringList(courses);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<Student> CREATOR = new Creator<Student>() {
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
}
// Kotlin中使用@Parcelize注解(需要添加插件)
@Parcelize
data class Student(
val name: String,
val age: Int,
val courses: List<String> = emptyList()
) : Parcelable
Activity之间的数据回传
使用startActivityForResult(已废弃)
// 旧方式(已废弃)
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CODE = 1001;
private void startForResult() {
Intent intent = new Intent(this, SelectActivity.class);
startActivityForResult(intent, REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
String result = data.getStringExtra("result");
// 处理返回的数据
}
}
}
使用Activity Result API(推荐)
// Java - 新方式
public class MainActivity extends AppCompatActivity {
// 注册结果回调
private final ActivityResultLauncher<Intent> selectLauncher =
registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
if (data != null) {
String selectedItem = data.getStringExtra("selected_item");
// 处理返回的数据
updateUI(selectedItem);
}
}
}
);
private void startSelectActivity() {
Intent intent = new Intent(this, SelectActivity.class);
selectLauncher.launch(intent);
}
}
// 返回数据的Activity
public class SelectActivity extends AppCompatActivity {
private void returnResult(String item) {
Intent resultIntent = new Intent();
resultIntent.putExtra("selected_item", item);
setResult(RESULT_OK, resultIntent);
finish();
}
}
// Kotlin - 使用Activity Result API
class MainActivity : AppCompatActivity() {
// 注册结果回调
private val selectLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.let { data ->
val selectedItem = data.getStringExtra("selected_item")
// 处理返回的数据
updateUI(selectedItem)
}
}
}
private fun startSelectActivity() {
val intent = Intent(this, SelectActivity::class.java)
selectLauncher.launch(intent)
}
}
使用ViewModel共享数据
对于复杂的数据共享场景,推荐使用ViewModel:
// 共享的ViewModel
class SharedViewModel : ViewModel() {
private val _selectedItem = MutableLiveData<String>()
val selectedItem: LiveData<String> = _selectedItem
fun selectItem(item: String) {
_selectedItem.value = item
}
}
// Activity A
class ActivityA : AppCompatActivity() {
private lateinit var viewModel: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
// 观察数据变化
viewModel.selectedItem.observe(this) { item ->
// 更新UI
}
}
}
示例:putExtra 与 Bundle 传值
在首页创建两个按钮
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="使用 putExtra 传递数据" />
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="使用 Bundle 传递数据" />
方法
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button btn1, btn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1 = findViewById(R.id.btn1);
btn1.setOnClickListener(this);
btn2 = findViewById(R.id.btn2);
btn2.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn1:
// 使用 putExtra 传递数据
Intent intent = new Intent(MainActivity.this, FirstActivity.class);
intent.putExtra("name", "王小明");
intent.putExtra("age", 12);
intent.putExtra("isPassed", true);
startActivity(intent);
break;
case R.id.btn2:
// 使用 Bundle 传递数据
Intent intent1 = new Intent(MainActivity.this, SecondActivity.class);
// 创建 Bundle 对象
Bundle bundle = new Bundle();
bundle.putString("name","王小明");
bundle.putInt("age",12);
intent1.putExtras(bundle);
startActivity(intent1);
break;
}
}
}
另外两个页面
<Button
android:id="@+id/btn3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="接收 putExtra 传递的数据" />
<TextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btn4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="接收 Bundle 传递的数据" />
<TextView
android:id="@+id/text2"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
接收方法
public class FirstActivity extends AppCompatActivity {
Button btn3;
TextView text1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
text1=findViewById(R.id.text1);
btn3=findViewById(R.id.btn3);
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 接收数据并显示在text1
Intent intent=getIntent();
String name = intent.getStringExtra("name");
int age = intent.getIntExtra("age",0);
boolean isPassed = intent.getBooleanExtra("isPassed",true);
text1.setText(name+":"+age+":"+isPassed);
}
});
}
}
public class SecondActivity extends AppCompatActivity {
Button btn4;
TextView text2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
text2 = findViewById(R.id.text2);
btn4 = findViewById(R.id.btn4);
btn4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 接收数据并显示在text2
Bundle bundle = getIntent().getExtras();
String name = bundle.getString("name");
int age = bundle.getInt("age");
text2.setText(name + ":" + age);
}
});
}
}

Jetpack组件
Navigation组件
Jetpack Navigation简化了应用内导航的实现:
1. 添加依赖
dependencies {
def nav_version = "2.5.3"
// Java
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
// Kotlin
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
}
2. 创建导航图
res/navigation/nav_graph.xml:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.example.HomeFragment"
android:label="Home"
tools:layout="@layout/fragment_home">
<action
android:id="@+id/action_home_to_detail"
app:destination="@id/detailFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
</fragment>
<fragment
android:id="@+id/detailFragment"
android:name="com.example.DetailFragment"
android:label="Detail"
tools:layout="@layout/fragment_detail">
<argument
android:name="itemId"
app:argType="integer"
android:defaultValue="0" />
</fragment>
</navigation>
3. 在Activity中设置Navigation
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
// 设置ActionBar
setupActionBarWithNavController(navController)
// 设置BottomNavigationView
val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_nav)
bottomNav.setupWithNavController(navController)
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp() || super.onSupportNavigateUp()
}
}
4. 导航操作
// 简单导航
findNavController().navigate(R.id.detailFragment)
// 传递参数
val bundle = bundleOf("itemId" to 123)
findNavController().navigate(R.id.detailFragment, bundle)
// 使用Safe Args(推荐)
val action = HomeFragmentDirections.actionHomeToDetail(itemId = 123)
findNavController().navigate(action)
Activity结果API
新的Activity Result API替代了过时的startActivityForResult:
class MainActivity : AppCompatActivity() {
// 选择图片
private val pickImage = registerForActivityResult(
ActivityResultContracts.GetContent()
) { uri: Uri? ->
uri?.let {
// 处理选中的图片
imageView.setImageURI(it)
}
}
// 请求权限
private val requestPermission = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
// 权限已授予
takePhoto()
} else {
// 权限被拒绝
showPermissionDeniedDialog()
}
}
// 拍照
private val takePicture = registerForActivityResult(
ActivityResultContracts.TakePicture()
) { success: Boolean ->
if (success) {
// 照片已保存
}
}
private fun selectImage() {
pickImage.launch("image/*")
}
private fun requestCameraPermission() {
requestPermission.launch(Manifest.permission.CAMERA)
}
}
性能优化
1. 避免内存泄漏
class MyActivity : AppCompatActivity() {
// 避免内部类持有外部类引用
companion object {
class MyHandler(activity: MyActivity) : Handler(Looper.getMainLooper()) {
private val weakReference = WeakReference(activity)
override fun handleMessage(msg: Message) {
weakReference.get()?.let { activity ->
// 处理消息
}
}
}
}
private lateinit var handler: MyHandler
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
handler = MyHandler(this)
}
override fun onDestroy() {
super.onDestroy()
handler.removeCallbacksAndMessages(null)
}
}
2. 优化启动速度
// 使用懒加载
class MainActivity : AppCompatActivity() {
private val heavyObject by lazy {
// 延迟初始化重量级对象
HeavyObject()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 异步加载数据
lifecycleScope.launch {
val data = withContext(Dispatchers.IO) {
loadDataFromDatabase()
}
updateUI(data)
}
}
}
3. 管理Activity栈
object ActivityManager {
private val activities = mutableListOf<WeakReference<Activity>>()
fun addActivity(activity: Activity) {
activities.add(WeakReference(activity))
}
fun removeActivity(activity: Activity) {
activities.removeAll { it.get() == activity || it.get() == null }
}
fun finishAll() {
activities.forEach { it.get()?.finish() }
activities.clear()
}
}
最佳实践
1. 使用AndroidX和Jetpack
// 使用AppCompatActivity而不是Activity
class MainActivity : AppCompatActivity() {
// 使用ViewBinding
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// 直接访问视图
binding.textView.text = "Hello"
binding.button.setOnClickListener {
// 处理点击
}
}
}
2. 处理配置变更
class MainActivity : AppCompatActivity() {
// 使用ViewModel保存数据
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ViewModel中的数据在配置变更后仍然存在
viewModel.data.observe(this) { data ->
updateUI(data)
}
}
}
3. 权限处理
class PermissionActivity : AppCompatActivity() {
private val requestMultiplePermissions = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
permissions.entries.forEach { entry ->
val permission = entry.key
val isGranted = entry.value
when {
isGranted -> {
// 权限已授予
}
shouldShowRequestPermissionRationale(permission) -> {
// 显示权限说明
}
else -> {
// 权限被永久拒绝
}
}
}
}
private fun requestPermissions() {
val permissions = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_FINE_LOCATION
)
requestMultiplePermissions.launch(permissions)
}
}
调试技巧
1. 生命周期日志
open class BaseActivity : AppCompatActivity() {
protected val TAG = javaClass.simpleName
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "onCreate")
}
override fun onStart() {
super.onStart()
Log.d(TAG, "onStart")
}
// 其他生命周期方法...
}
2. 使用ADB命令
# 查看Activity栈
adb shell dumpsys activity activities
# 启动Activity
adb shell am start -n com.example.app/.MainActivity
# 强制停止应用
adb shell am force-stop com.example.app
# 查看当前Activity
adb shell dumpsys activity top
3. 使用Layout Inspector
在Android Studio中:
- Tools → Layout Inspector
- 选择进程和Activity
- 查看视图层级和属性
常见问题
问题1:Activity未注册
错误信息:
android.content.ActivityNotFoundException: Unable to find explicit activity class
解决方案: 在AndroidManifest.xml中注册Activity:
<activity android:name=".YourActivity" />
问题2:数据丢失
问题描述: 旋转屏幕后数据丢失
解决方案:
- 使用
onSaveInstanceState保存数据 - 使用ViewModel
- 在manifest中配置
android:configChanges
问题3:内存泄漏
常见原因:
- Handler持有Activity引用
- 静态变量持有Activity
- 监听器未注销
解决方案:
override fun onDestroy() {
super.onDestroy()
// 移除所有回调
handler.removeCallbacksAndMessages(null)
// 注销监听器
unregisterReceiver(receiver)
// 取消协程
job?.cancel()
}
相关文章
Android开发基础
- Android界面布局开发实战指南 - 布局基础
- Android界面控件详解 - 控件使用
- Android事件处理 - 事件机制
组件通信
进阶主题
- 网络编程 - 网络请求
- Material Design - 设计规范
- Jetpack指南 - 官方文档
总结
Activity是Android应用的核心组件,掌握其生命周期和使用方法对于开发高质量应用至关重要。
🎯 核心要点
- 生命周期管理:理解并正确处理各个生命周期方法
- 数据传递:掌握Intent、Bundle等数据传递方式
- 导航管理:使用Navigation组件简化导航逻辑
- 性能优化:避免内存泄漏,优化启动速度
🛠️ 开发建议
- 使用Jetpack组件提高开发效率
- 遵循单一职责原则,避免Activity过于臃肿
- 合理使用启动模式管理Activity栈
- 重视用户体验,提供流畅的页面转场