【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 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui