Android 活动(Activity)(保姆级教程)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

在 Android 开发的浩瀚海洋中,"Android 活动(Activity)" 是开发者必须掌握的核心概念之一。它如同应用程序的窗口,承载着用户与设备交互的每一帧画面。无论是展示登录界面、处理表单数据,还是构建复杂的导航逻辑,Activity 都是实现这些功能的基础单元。本文将从 Activity 的基本原理、生命周期管理、启动模式到数据传递等维度,结合代码示例和形象比喻,帮助开发者系统性地理解这一概念,并在实际项目中灵活运用。


一、什么是 Android 活动(Activity)?

Activity 是 Android 系统中用于承载用户界面的组件,可以将其想象为一座“房间”,每个房间代表应用中的一个独立功能场景。例如,登录界面、商品详情页、设置面板等,都可视为不同的 Activity。

核心特性

  1. 用户交互入口:Activity 是用户直接操作的界面载体,所有按钮点击、输入框交互均通过 Activity 实现。
  2. 生命周期管理:每个 Activity 会经历创建、运行、暂停、销毁等状态,开发者需在这些阶段处理资源分配与释放。
  3. 堆栈式管理:Activity 按“后进先出”原则存放在任务栈中,确保用户返回操作的流畅性。

比喻
可以把 Activity 理解为电影院的放映厅。每个放映厅(Activity)播放不同的电影(功能),观众(用户)通过检票口(Intent)进入特定厅,而影院经理(系统)负责管理所有放映厅的开放与关闭状态。


二、Activity 的生命周期详解

Activity 的生命周期由系统严格控制,开发者需在关键回调方法中执行特定操作。以下是核心状态转换图:

状态描述典型应用场景
onCreate()Activity 被创建时调用,用于初始化视图和数据。加载布局、绑定数据源
onStart()Activity 变为可见但尚未获取焦点时触发。准备监听器或开始动画
onResume()Activity 获得用户交互权限,处于可操作状态。恢复网络请求、开始传感器监听
onPause()Activity 失去焦点,可能被新 Activity 覆盖。保存用户输入数据、暂停动画
onStop()Activity 完全不可见,可能被销毁。释放资源(如摄像头、文件句柄)
onDestroy()Activity 被系统回收前最后调用的方法。彻底释放所有资源

生命周期代码示例

public class MainActivity extends AppCompatActivity {  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        // 初始化视图和数据  
        Log.d("Lifecycle", "onCreate: 页面创建");  
    }  

    @Override  
    protected void onStart() {  
        super.onStart();  
        Log.d("Lifecycle", "onStart: 页面可见");  
    }  

    @Override  
    protected void onResume() {  
        super.onResume();  
        Log.d("Lifecycle", "onResume: 页面可交互");  
    }  

    @Override  
    protected void onPause() {  
        super.onPause();  
        Log.d("Lifecycle", "onPause: 页面暂停");  
    }  

    @Override  
    protected void onStop() {  
        super.onStop();  
        Log.d("Lifecycle", "onStop: 页面不可见");  
    }  

    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        Log.d("Lifecycle", "onDestroy: 页面销毁");  
    }  
}  

关键点提醒

  • 资源管理:避免在 onCreate() 中执行耗时操作,如网络请求或复杂计算,可改用异步线程。
  • 数据保存:在 onSaveInstanceState() 中保存临时数据,防止 Activity 被意外销毁后数据丢失。

三、Activity 的启动模式(Launch Mode)

启动模式决定了 Activity 的实例化方式和任务栈的管理策略。Android 提供了四种核心模式:

1. Standard(标准模式)

默认模式,每次启动都会创建新实例,堆栈中可存在多个相同 Activity。
场景:浏览商品列表时,点击每个商品进入详情页,可使用此模式。

<!-- AndroidManifest.xml 配置 -->  
<activity  
    android:name=".DetailActivity"  
    android:launchMode="standard" />  

2. SingleTop(单实例栈顶复用)

若目标 Activity 已位于任务栈顶部,则直接复用,否则创建新实例。
场景:连续点击通知栏多次跳转同一页面时,避免重复创建。

// 启动 Activity 时的 Intent 标志  
Intent intent = new Intent(this, DetailActivity.class);  
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);  

3. SingleTask(单实例任务栈)

系统会为该 Activity 创建独立的任务栈,且同一栈内仅保留一个实例。
场景:应用入口 Activity,防止重复启动。

<activity  
    android:name=".MainActivity"  
    android:launchMode="singleTask" />  

4. SingleInstance(全局单实例)

仅创建一个实例,并且该实例存在于独立的任务栈中,全局唯一。
场景:系统级服务类应用(如拨号器),需与其他应用完全隔离。

比喻
启动模式如同交通规则:

  • Standard 是普通车道,允许重复通行;
  • SingleTop 是单行道入口,若已有车辆在前则并线;
  • SingleTask 是专用通道,仅允许一辆车通行;
  • SingleInstance 是私人车道,与其他车道完全隔离。

四、Activity 间数据传递与返回结果

1. 显式 Intent 传递基础数据

通过 Intent 的 putExtra() 方法传递简单数据类型(如 String、int)。

// 发送方  
Intent intent = new Intent(CurrentActivity.this, TargetActivity.class);  
intent.putExtra("user_id", 123);  
intent.putExtra("username", "Alice");  
startActivity(intent);  

// 接收方  
Intent intent = getIntent();  
int userId = intent.getIntExtra("user_id", 0);  
String username = intent.getStringExtra("username");  

2. 使用 Bundle 传递复杂对象

若需传递自定义对象,需实现 Serializable 或 Parcelable 接口。

// 定义 Parcelable 对象  
public class User implements Parcelable {  
    private String name;  
    private int age;  

    // Parcelable 实现代码略...  
}  

// 发送方  
User user = new User("Bob", 25);  
Intent intent = new Intent(this, ProfileActivity.class);  
intent.putExtra("user", user);  

// 接收方  
User user = (User) intent.getParcelableExtra("user");  

3. 启动 Activity 并获取返回结果

通过 startActivityForResult() 启动 Activity,并在 onActivityResult() 中接收结果。

// 发送方  
Intent intent = new Intent(this, EditActivity.class);  
startActivityForResult(intent, 1001);  

// 接收结果  
@Override  
protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
    if (requestCode == 1001 && resultCode == RESULT_OK) {  
        String editedText = data.getStringExtra("edited_data");  
    }  
}  

// 接收方返回数据  
Intent resultIntent = new Intent();  
resultIntent.putExtra("edited_data", "修改后的文本");  
setResult(RESULT_OK, resultIntent);  
finish();  

五、Activity 的内存优化与进阶技巧

1. 避免内存泄漏

当 Activity 被销毁后,若存在未释放的引用(如线程、监听器),可能导致内存泄漏。

// 错误示例:未取消的异步任务  
new Thread(() -> {  
    // 网络请求后调用 UI 操作  
    runOnUiThread(() -> textView.setText("加载完成"));  
}).start();  

// 正确做法:在 onDestroy() 中取消任务  
@Override  
protected void onDestroy() {  
    super.onDestroy();  
    if (task != null && !task.isCancelled()) {  
        task.cancel(true);  
    }  
}  

2. 配合 ViewModel 保存状态

使用 AndroidX 的 ViewModel 类,可跨配置变化(如屏幕旋转)保存数据。

// 定义 ViewModel  
public class MainViewModel extends ViewModel {  
    private MutableLiveData<String> username = new MutableLiveData<>();  

    public LiveData<String> getUsername() {  
        return username;  
    }  
}  

// Activity 中使用  
MainViewModel viewModel = new ViewModelProvider(this).get(MainViewModel.class);  
viewModel.getUsername().observe(this, username -> {  
    // 更新 UI  
});  

3. 任务栈管理优化

通过 Intent 标志控制 Activity 的启动行为:

// 清空当前任务栈,以新 Activity 为根  
Intent intent = new Intent(this, NewActivity.class);  
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);  

六、常见问题与解决方案

1. Activity 重复创建问题

现象:旋转屏幕或从后台返回时,页面数据丢失。
解决方案:在 onSaveInstanceState() 中保存数据,并在 onCreate() 中恢复。

@Override  
protected void onSaveInstanceState(Bundle outState) {  
    super.onSaveInstanceState(outState);  
    outState.putString("text", editText.getText().toString());  
}  

@Override  
protected void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  
    if (savedInstanceState != null) {  
        String text = savedInstanceState.getString("text");  
        editText.setText(text);  
    }  
}  

2. Activity 堆栈溢出

现象:频繁跳转导致内存占用过高。
解决方案:使用 SingleTop 或 SingleTask 模式,或在跳转时指定 FLAG_ACTIVITY_CLEAR_TOP 标志。

Intent intent = new Intent(this, MainActivity.class);  
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);  

结论

Android 活动(Activity)是构建应用界面的核心组件,其生命周期管理、启动模式选择和数据交互能力,直接影响着用户体验与系统资源效率。开发者需深入理解 Activity 的运行机制,并通过合理的设计(如 ViewModel、启动标志)规避常见问题。随着 Jetpack 组件(如 Navigation Component)的普及,Activity 的使用场景虽有所变化,但其作为 Android 架构基石的地位仍不可替代。建议读者结合官方文档与开源项目,持续探索更复杂的场景实现。


延伸学习

  • 阅读《Android 开发艺术探索》中关于 Activity 生命周期的章节
  • 实践 Navigation 组件在 Jetpack 体系中的 Activity 管理
  • 探索 Process 生命周期对 Activity 的影响

最新发布