【Android】四大组件Activity

Activity基础概念

1. 定义与作用

  • Android 四大组件之一,是用户界面的载体,负责与用户交互。
  • 一个应用可包含多个 Activity,通过 Intent 切换。

2. 层次结构

  • Activity 通常放在 任务栈(Task Stack) 中管理,遵循后进先出(LIFO)原则。
  • 任务栈可跨应用,如从应用 A 启动应用 B 的 Activity,B 的 Activity 会加入 A 的任务栈。

3. Activity与Context的关系

  • Activity 是 Context 的子类,可直接使用 Context 的方法(如 getResources()startActivity())。
java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Study"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

此元素的唯一必需属性是 [android:name],用于指定 activity 的类名称。您还可以添加属性 ,用于定义标签、图标或界面主题等 activity 特征。

Activity生命周期

一个 activity 在其生命周期中会经历多种状态。 您可以使用一系列回调来处理状态之间的转换。 developer.android.google.cn/guide/compo...

  • onCreate ():Activity 首次创建时调用,用于初始化组件、设置布局等
  • onStart ():Activity 即将可见时调用
  • onResume ():Activity 获得焦点、可交互时调用
  • onPause ():Activity 失去焦点、即将转入后台时调用
  • onStop ():Activity 完全不可见时调用
  • onRestart ():Activity 从停止状态重新启动时调用
  • onDestroy ():Activity 被销毁时调用

常见问题

  1. Android Activity 重复调用 onCreate () 的原因
  2. 跳转时未调用 onDestroy () 的核心原因
  3. 屏幕旋转时生命周期变化
  4. 屏幕旋转时的完整生命周期流程

Activity启动模式

在 Android 开发中,Activity 的启动模式(Launch Mode)、任务(Task)和返回栈(Back Stack)是实现应用导航逻辑的核心概念。理解这些机制对于构建流畅的用户体验和优化内存管理至关重要。

1. 四种启动模式

启动模式 核心特性 应用场景
standard 每次启动都创建新实例,无论目标 Activity 是否已存在于栈中 默认模式,普通页面跳转
singleTop 若目标 Activity 位于栈顶,则复用该实例;否则创建新实例 通知栏点击跳转、搜索结果页
singleTask 任务内单实例:若目标 Activity 存在于栈中,则清除其上方所有 Activity 应用主界面、浏览器主窗口
singleInstance 全局单实例:独占一个任务栈,不与其他 Activity 共存 系统级应用(如来电界面)

2. 启动模式设置

AndroidManifest.xml

java 复制代码
<activity
    android:name=".StandardActivity"
    android:launchMode="standard" />

Intent 标志位

标志位 作用
FLAG_ACTIVITY_NEW_TASK 类似 singleTask,通常用于从非 Activity 上下文启动 Activity
FLAG_ACTIVITY_SINGLE_TOP 类似 singleTop,启动时若目标 Activity 在栈顶则复用
FLAG_ACTIVITY_CLEAR_TOP 清除目标 Activity 上方的所有 Activity,通常与 NEW_TASK 配合使用
FLAG_ACTIVITY_REORDER_TO_FRONT 将已存在的 Activity 移至栈顶,不创建新实例
java 复制代码
Intent intent = new Intent(this, MainActivity.class); 
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 
startActivity(intent);

3. 启动模式示例

1. standard 模式

ini 复制代码
<activity
    android:name=".StandardActivity"
    android:launchMode="standard" />

行为 :每次启动都会创建新实例
任务栈变化

css 复制代码
初始栈:[MainActivity]
启动 StandardActivity:[MainActivity, StandardActivity]
再次启动:[MainActivity, StandardActivity, StandardActivity]

2. singleTop 模式

ini 复制代码
<activity
    android:name=".SingleTopActivity"
    android:launchMode="singleTop" />

行为

  • 若目标 Activity 在栈顶:调用 onNewIntent() 而非创建新实例
  • 若不在栈顶:创建新实例

任务栈变化

css 复制代码
初始栈:[MainActivity, SingleTopActivity]
再次启动 SingleTopActivity(在栈顶):[MainActivity, SingleTopActivity](复用)
启动其他 Activity:[MainActivity, SingleTopActivity, OtherActivity]
再次启动 SingleTopActivity(不在栈顶):[MainActivity, SingleTopActivity, OtherActivity, SingleTopActivity]

3. singleTask 模式

ini 复制代码
<activity
    android:name=".MainActivity"
    android:launchMode="singleTask"
    android:taskAffinity="com.example.app" />

行为

  • 若目标 Activity 不存在于任何任务:创建新任务并实例化
  • 若存在:将该任务移至前台,并清除其上方所有 Activity

任务栈变化

css 复制代码
初始栈:[MainActivity, ActivityB, ActivityC]
启动 MainActivity(已存在):[MainActivity](清除 B 和 C)

4. singleInstance 模式

ini 复制代码
<activity
    android:name=".SingleInstanceActivity"
    android:launchMode="singleInstance" />

行为

  • 目标 Activity 独占一个任务栈
  • 该任务栈中永远只有这一个 Activity

任务栈变化

css 复制代码
初始任务 Task1:[MainActivity]
启动 SingleInstanceActivity:
  Task1:[MainActivity]
  Task2:[SingleInstanceActivity]
从 SingleInstanceActivity 启动 ActivityB:
  Task1:[MainActivity, ActivityB]
  Task2:[SingleInstanceActivity]

Activity 数据传递与回调

1. 数据传递方式

  • Intent 携带数据
java 复制代码
// 创建 Intent 并添加参数
Intent intent = new Intent(CurrentActivity.this, TargetActivity.class);
intent.putExtra("key_string", "Hello World");  // 传递字符串
intent.putExtra("key_int", 123);               // 传递整数
intent.putExtra("key_boolean", true);          // 传递布尔值

// 传递自定义对象(需实现 Serializable 或 Parcelable 接口)
User user = new User("John", 25);
intent.putExtra("key_object", user);

// 启动 Activity
startActivity(intent);
java 复制代码
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_target);
    
    // 获取启动该 Activity 的 Intent
    Intent intent = getIntent();
    
    // 从 Intent 中获取参数
    String strValue = intent.getStringExtra("key_string");
    int intValue = intent.getIntExtra("key_int", 0);  // 第二个参数是默认值
    boolean boolValue = intent.getBooleanExtra("key_boolean", false);
    
    // 获取自定义对象
    User user = (User) intent.getSerializableExtra("key_object");
}
  • Bundle 传递复杂数据:
java 复制代码
// 创建 Bundle 对象并添加数据
Bundle bundle = new Bundle();
bundle.putString("name", "Alice");
bundle.putInt("age", 30);
bundle.putStringArrayList("hobbies", new ArrayList<>(Arrays.asList("reading", "swimming")));

// 将 Bundle 放入 Intent
Intent intent = new Intent(CurrentActivity.this, TargetActivity.class);
intent.putExtras(bundle);

// 启动 Activity
startActivity(intent);
java 复制代码
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_target);
    
    // 获取 Bundle
    Bundle bundle = getIntent().();
    if (bundle != null) {
        String name = bundle.getString("name");
        int age = bundle.getInt("age");
        ArrayList<String> hobbies = bundle.getStringArrayList("hobbies");
    }
}
  • 静态变量:通过静态类或单例模式存储数据。
  • ViewModel 共享数据 :在 Activity 间通过 ViewModel 共享数据(需配合 Jetpack)。

2. 数据回调方式

  • 旧方式(已弃用)onActivityResult() + startActivityForResult()
  • 新方式(Activity Result API)
java 复制代码
ActivityResultLauncher<Intent> launcher = registerForActivityResult(
                new ActivityResultContracts.StartActivityForResult(),
                result -> { if (result.getResultCode() == RESULT_OK) {
                    Intent data = result.getData();
                    // 处理返回数据
                    }
                });
// 启动 Activity
Intent intent = new Intent(this, SecondActivity.class);
launcher.launch(intent);

Activity UI 与布局

1. 加载布局的方式

  • setContentView(R.layout.activity_main):在 onCreate() 中加载布局文件。
  • 动态加载布局:
java 复制代码
LinearLayout root = findViewById(R.id.root_layout); 
View childView = LayoutInflater.from(this).inflate(R.layout.child_layout, root, false); 
root.addView(childView);

2. UI组件交互

  • 查找 View:findViewById() 或使用 Kotlin 的 by viewBindings
  • 设置监听器:
java 复制代码
Button button = findViewById(R.id.button); 
button.setOnClickListener(v -> { // 处理点击事件 });

3. Fragment 与 Activity 协作

  • Activity 中添加 Fragment:
java 复制代码
getSupportFragmentManager()
.beginTransaction() 
.add(R.id.fragment_container, new MyFragment()) 
.commit();
  • Fragment 与 Activity 通信:通过接口或 ViewModel

Activity状态管理

1. 临时状态保存

  • onSaveInstanceState(Bundle outState):在 Activity 可能被销毁前调用,保存临时数据(如文本框内容)。
  • onRestoreInstanceState(Bundle savedInstanceState):在 onCreate() 后恢复数据。
java 复制代码
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    // 获取保存的文本内容并恢复到文本框中
    String myText = savedInstanceState.getString("my_text");
    myEditText.setText(myText);
}
java 复制代码
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (savedInstanceState != null) {
        // 恢复保存的数据
        String myText = savedInstanceState.getString("my_text");
        myEditText.setText(myText);
    }
}

2. 配置变更处理

  • 默认重建 :屏幕旋转等配置变更会导致 Activity 重建,需通过 savedInstanceState 恢复状态。
  • 禁止重建 :在 AndroidManifest.xml 中设置 android:configChanges="orientation|screenSize",并在 onConfigurationChanged() 中处理变更。
java 复制代码
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Log.d("MainActivity", "Orientation changed to Landscape");
        setContentView(R.layout.activity_main_landscape);
        // 恢复EditText的内容
        if (savedUsername != null) {
            etUsername = findViewById(R.id.et_username); // 需要重新获取EditText引用
            etUsername.setText(savedUsername);
        }
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        Log.d("MainActivity", "Orientation changed to Portrait");
        setContentView(R.layout.activity_main);
        // 恢复EditText的内容
        if (savedUsername != null) {
            etUsername = findViewById(R.id.et_username); // 重新获取EditText引用
            etUsername.setText(savedUsername);
        }
    }
}

Activity常见问题

  1. Activity 生命周期的各个阶段及其作用?
  2. 屏幕旋转时 Activity 的重建过程及如何避免?
  3. Activity 启动模式的区别和应用场景?
  4. 如何在 Activity 间传递大数据(超过 1MB)?
  5. Activity 和 Fragment 的关系与区别?
  6. 如何优化 Activity 的启动速度?
相关推荐
没有了遇见2 分钟前
Activity 启动模式总结
android
wangjialelele19 分钟前
二叉树基本学习
android
雨白4 小时前
Android 音视频播放:MediaPlayer 与 VideoView
android
Harry技术4 小时前
Fragment 和 AppCompatActivity 两个核心组件设计的目的和使用场景对比
android·android studio
Wgllss4 小时前
Kotlin + Flow 实现责任链模式的4种案例
android·架构·android jetpack
Digitally5 小时前
如何通过 7 种有线或无线方式将视频从 PC 传输到 Android
android
Carpoor奇5 小时前
Mybatis之Integer类型字段为0,入库为null
android·mybatis
草明6 小时前
解决: React Native android webview 空白页
android·react native·react.js
Digitally7 小时前
如何轻松地将照片从电脑传输到安卓手机
android·智能手机·电脑