从 MainActivity 到 EntryAbility:Android 和 HarmonyOS 的第一屏是怎么启动的

打开一个新工程时,目录只能告诉我们“文件在哪里”。真正开始写代码,还要知道另一件事:用户点了桌面图标之后,系统先找到谁,谁再把第一屏显示出来。

这篇就从这个动作开始。Android 侧看 AndroidManifest.xmlMainActivity,HarmonyOS 侧看 module.json5EntryAbility。先把入口跑通,再谈页面跳转、状态管理和业务架构,会更稳。

Android:先从 Manifest 找到启动 Activity

Android 应用不是因为某个类叫 MainActivity 就自动启动它。系统会先看 AndroidManifest.xml,找到带有启动意图的 Activity。

<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>

这段配置可以拆成三层看:

配置 作用 初学时怎么记
android:name=".MainActivity" 指向要启动的 Activity 类 系统最终会实例化它
MAIN action 说明这是应用的主入口动作 “我要启动应用”
LAUNCHER category 说明它可以出现在桌面启动器里 “桌面图标点我”

进入 MainActivity 后,第一屏通常在 onCreate() 里挂载。

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            HomeScreen()
        }
    }
}

如果是 View/XML 项目,则可能是:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

可以把 Android 第一屏启动链路理解成这样:

Android 第一屏启动链路

这里的关键不是 setContentsetContentView 哪个更现代,而是 Activity 站在系统入口和 UI 内容之间:它接住系统启动请求,再把第一屏挂到窗口里。

HarmonyOS:先从 module.json5 找到 EntryAbility

HarmonyOS Stage 模型里,入口声明在 module.json5。以华为代码工坊官方样例 sample_in_harmonyos 的 phone 模块为例,入口相关配置大致长这样:

{
  "module": {
    "name": "phone",
    "type": "entry",
    "mainElement": "EntryAbility",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "exported": true,
        "skills": [
          {
            "entities": ["entity.system.home"],
            "actions": ["action.system.home"]
          }
        ]
      }
    ]
  }
}

这段配置也可以拆开看:

配置 作用 初学时怎么记
mainElement 标记模块的主要入口元素 这个模块默认先看谁
abilities.name 声明一个 Ability 类似“这个模块有哪些可被系统调度的能力”
srcEntry 指向 Ability 的 ArkTS 文件 顺着它找到 EntryAbility.ets
skills 描述可被匹配的动作与实体 这里承担桌面启动入口的匹配信息

对应的 EntryAbility.ets 可以先看骨架:

import { UIAbility, Want, AbilityConstant } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // 处理启动参数,准备应用级初始化
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index');
  }

  onForeground(): void {
    // Ability 进入前台
  }

  onBackground(): void {
    // Ability 进入后台
  }

  onDestroy(): void {
    // Ability 销毁,释放资源
  }
}

和 Android 最大的手感差异在 onWindowStageCreate():Ability 创建之后,系统还会创建窗口舞台,页面内容通常在这里通过 windowStage.loadContent(...) 加载。

HarmonyOS 第一屏启动链路

代码工坊样例里,phone 模块不是直接进入首页,而是先加载 page/SplashPage,再进入主页面。这里的 SplashPage 可以理解为启动过渡页:它通常用于展示启动画面、承接初始化结果或做路由分发。它不是一个新的系统概念,只是业务里常见的“启动后先看到的过渡页面”。

Want 和 Intent:入口参数放在哪里

在 Android 里,Activity 启动时经常从 intent 里取参数:

class DetailActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val articleId = intent.getStringExtra("article_id")
    }
}

HarmonyOS 的 UIAbility.onCreate() 会收到 want

onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  const articleId = want.parameters?.['article_id'] as string | undefined;
}

可以先用这个小表建立直觉:

问题 Android Intent HarmonyOS Want
它是什么 启动组件和传递参数的信息载体 启动 Ability 和传递参数的信息载体
常见入口 activity.intentonNewIntent() onCreate(want, launchParam)onNewWant()
参数位置 extras parameters
显式目标 component / package / class bundleName / abilityName
迁移时要小心 不要只把它当成 key/value 包,Intent 还涉及隐式匹配规则 不要只把它当成 extras,Want 还承载 Ability 与设备等语境

这篇不展开 Intent 和 Want 的全部差异,先抓入口层最常见的一点:启动参数可以在入口生命周期里读取,但不要让入口生命周期承担复杂业务。

更稳的做法是:入口读取 Intent / Want 后,把它转成页面路由或业务事件,再交给导航层、页面状态或业务层处理。

生命周期:不要硬凑方法名,要看阶段

Activity 和 UIAbility 都有生命周期,但不能把方法名一一硬套。先把两张官方生命周期图放在一起看,会更容易看到差异:Android 的 Activity 生命周期更围绕“可见/可交互/停止/销毁”展开,HarmonyOS 的 UIAbility 还要额外关注 WindowStage 这一层。

Android Activity 生命周期

Android Activity lifecycle

HarmonyOS UIAbility 生命周期

HarmonyOS UIAbility lifecycle

按阶段对齐,会比按方法名对齐更清楚:

阶段 Android 里常看哪里 HarmonyOS 里常看哪里 开发时关注什么
创建入口 Activity.onCreate() UIAbility.onCreate() 读取启动参数、准备轻量初始化
加载第一屏 setContent / setContentView windowStage.loadContent(...) 把页面挂到窗口,不把业务塞满
进入前台 onResume() onForeground() 恢复交互、刷新轻量状态
退到后台 onPause() / onStop() onBackground() 暂停资源、保存必要状态
销毁释放 onDestroy() onWindowStageDestroy() / onDestroy() 释放监听、订阅、长连接等资源

举个很小的迁移例子:如果 Android 里你在 onResume() 做页面可见后的轻量刷新,到 HarmonyOS 里不要直接找一个“同名方法”,而是先问:这个刷新是和 Ability 回到前台有关,还是和某个 ArkUI 页面显示有关?前者可能放在 onForeground(),后者更适合放在页面自己的生命周期或状态刷新逻辑里。

第一屏页面:@Entry 不是 UIAbility

HarmonyOS 页面里经常能看到这样的写法:

@Entry
@Component
struct Index {
  build() {
    Column() {
      Text('CodeHubble')
      Button('开始学习')
        .onClick(() => {
          // TODO
        })
    }
  }
}

@Entry 标记的是页面入口组件,不是应用入口 Ability。简单说:

  • EntryAbility 是系统调度的 Ability,负责接住应用启动、创建窗口、加载页面;
  • @Entry 组件是某个页面文件里的入口 UI 组件,负责描述这页的界面;
  • 一个页面文件里通常只应该有一个 @Entry
  • 其他可复用 UI 组件可以用 @Component;如果项目使用状态管理 V2,再按规范使用 @ComponentV2 组织自定义组件。

也就是说,初学时可以按这个顺序找代码:

HarmonyOS 页面入口关系

这个顺序很重要。不要只在 pages/Index.ets 里找入口,否则会漏掉系统真正调度 Ability 的那一层。

初始化应该放哪:把模糊的“入口附近”拆开

入口文件很容易越写越胖。下面这张表可以作为迁移时的第一版整理规则:

事情 Android 更明确的位置 HarmonyOS 更明确的位置 建议
读取启动参数 Activity.onCreate() 读取 intent;新 Intent 看 onNewIntent() UIAbility.onCreate(want, launchParam);新 Want 看 onNewWant() 入口读取,尽快转给路由或业务事件
挂第一屏 Activity.onCreate()setContent / setContentView UIAbility.onWindowStageCreate()windowStage.loadContent(...) 入口负责挂载,不负责首页业务细节
应用级初始化 自定义 Application.onCreate(),或 DI 框架初始化入口 ApplicationContext、Ability 启动阶段、必要的全局状态初始化 只放轻量、确定、必要的初始化
页面数据加载 ViewModel / Repository / use case 页面状态容器、业务层、服务类 不要阻塞入口生命周期
订阅与监听 onStart/onResume 注册,onPause/onStop/onDestroy 释放 onForeground/onBackground/onWindowStageDestroy/onDestroy 配对处理 注册和释放要成对出现
深链/通知/卡片拉起分发 Intent 解析后交给导航层 Want 解析后交给路由或页面层 入口只做分发,不做复杂业务判断

如果只记一句话:入口层负责接系统、挂窗口、分发参数;业务层负责决定数据怎么来、页面怎么变。

最后再汇总一次

前面逐层拆完后,再看总表会更有感觉:

关注点 Android 常见写法 HarmonyOS 常见写法 迁移时先怎么理解
应用入口组件 MainActivity / 其他启动 Activity EntryAbility / 其他 UIAbility 都是系统调度的组件,不是普通函数入口
入口声明位置 AndroidManifest.xmlactivity + intent-filter module.json5abilities + skills 先看配置,再看代码
第一屏加载 setContentView(...) 或 Compose setContent { ... } windowStage.loadContent(...) Android 常在 Activity 里挂 UI,HarmonyOS 在窗口舞台创建后加载页面
启动参数 Intent / extras Want / parameters 先读参数,再分发给路由或业务层
页面入口 Compose @Composable 或 XML layout @Entry + @Component / @ComponentV2 UI 页面入口和系统 Ability 入口是两层
生命周期 Activity 生命周期 UIAbility + WindowStage 生命周期 按“创建、挂屏、前台、后台、销毁”理解,不要硬凑方法名

这条启动链路理清之后,后面的 Intent vs Want、页面路由、状态管理才有落点:它们不是孤立 API,而是沿着入口、页面、生命周期一层层长出来的。

参考素材

  • Android Activity 官方介绍:https://developer.android.com/guide/components/activities/intro-activities
  • Android Activity lifecycle 官方指南:https://developer.android.com/guide/components/activities/activity-lifecycle
  • OpenHarmony UIAbility lifecycle 官方文档:https://gitee.com/openharmony/docs/blob/master/en/application-dev/application-models/uiability-lifecycle.md
  • HarmonyOS UIAbility 组件概述:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/uiability-overview
  • HarmonyOS UIAbility 生命周期:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/uiability-lifecycle
  • 华为代码工坊官方样例:<https://gitcode.com/HarmonyOS_Samples/sample_in_harmonyos>

// Kai@CodeHubble

// 观测坐标:Android-HarmonyOS/2026-05-08

上一篇