HarmonyOS开发:Android迁移鸿蒙——架构对比与迁移策略

举报
Jack20 发表于 2026/06/28 21:02:56 2026/06/28
【摘要】 HarmonyOS开发:Android迁移鸿蒙——架构对比与迁移策略📌 核心要点:Android到鸿蒙的迁移不是简单的API替换,而是从命令式到声明式的思维范式转换,理解Activity→Ability、XML→ArkTS的映射关系是迁移的第一步。 背景与动机你是一个Android老手,写了三五年Kotlin,闭着眼睛都能撸出一个MVVM架构。突然有一天,老板说:“咱们的App要上鸿蒙。...

HarmonyOS开发:Android迁移鸿蒙——架构对比与迁移策略

📌 核心要点:Android到鸿蒙的迁移不是简单的API替换,而是从命令式到声明式的思维范式转换,理解Activity→Ability、XML→ArkTS的映射关系是迁移的第一步。

背景与动机

你是一个Android老手,写了三五年Kotlin,闭着眼睛都能撸出一个MVVM架构。突然有一天,老板说:“咱们的App要上鸿蒙。”

你打开DevEco Studio,一看——ArkTS?Ability?@State?这都什么跟什么?

别慌。Android迁移鸿蒙,本质上就是换了一套开发范式。你积累的架构思维、设计模式、业务逻辑,大部分都能复用。真正要变的,是你写代码的"姿势"。

为什么必须迁移?市场数据摆在那儿——鸿蒙设备覆盖量已经突破8亿,而且还在加速。你不去适配,就等于把用户往外推。但迁移不是重写,如果你把现有Android代码推倒重来,那不是迁移,那是自杀。

这篇文章,就是帮你理清Android和鸿蒙的架构差异,给你一张清晰的迁移路线图。

核心原理

架构对比:两套完全不同的设计哲学

Android的架构,说白了就是"命令式+组件化"。你用XML写布局,用Kotlin/Java写逻辑,通过findViewById或者DataBinding把两者绑在一起。Activity是核心,所有东西都围着它转。

鸿蒙呢?声明式+分布式。你用ArkTS一把梭,UI和逻辑写在一起,用@State驱动刷新。Ability是核心,但它比Activity轻得多,更像一个容器。

先看这张对比图:

graph TB
    subgraph Android["Android 架构"]
        A1[Activity] --> A2[Fragment]
        A1 --> A3[Service]
        A1 --> A4[BroadcastReceiver]
        A1 --> A5[ContentProvider]
        A2 --> A6[XML Layout]
        A2 --> A7[ViewModel]
        A7 --> A8[LiveData]
    end
    
    subgraph HarmonyOS["鸿蒙架构"]
        H1[UIAbility] --> H2[Page]
        H1 --> H3[ExtensionAbility]
        H2 --> H4[ArkTS 声明式UI]
        H2 --> H5[@State/@Link]
        H5 --> H6[AppStorage]
        H3 --> H7[ServiceExtension]
        H3 --> H8[DataShareExtension]
    end
    
    classDef androidStyle fill:#3DDC84,stroke:#2E7D32,color:#000,font-weight:bold
    classDef harmonyStyle fill:#0A59F7,stroke:#0A3CC7,color:#fff,font-weight:bold
    
    class A1,A2,A3,A4,A5,A6,A7,A8 androidStyle
    class H1,H2,H3,H4,H5,H6,H7,H8 harmonyStyle

四大组件映射关系

Android有四大组件,鸿蒙怎么对应?直接看表:

Android组件 鸿蒙对应 关键差异
Activity UIAbility UIAbility更轻量,一个Ability可管理多个Page
Fragment 自定义组件(@Component) 不再有Fragment生命周期,组件即Fragment
Service ServiceExtension / 后台任务 鸿蒙对后台限制更严格
BroadcastReceiver CommonEvent 订阅机制类似,但权限管理更细
ContentProvider DataShareExtension 分布式数据共享能力更强

这里面最大的坑在哪?Activity→UIAbility的映射。

Android里,一个Activity就是一个页面,生命周期方法一堆:onCreate、onStart、onResume、onPause、onStop、onDestroy。你在这堆方法里塞了多少逻辑?

鸿蒙的UIAbility生命周期简化了很多:onCreate、onWindowStageCreate、onForeground、onBackground、onDestroy。少了onStart/onResume/onPause/onStop,因为页面级别的生命周期交给了@Component。

生命周期映射

graph LR
    subgraph Android生命周期
        A_CREATE[onCreate] --> A_START[onStart]
        A_START --> A_RESUME[onResume]
        A_RESUME --> A_PAUSE[onPause]
        A_PAUSE --> A_STOP[onStop]
        A_STOP --> A_DESTROY[onDestroy]
    end
    
    subgraph 鸿蒙UIAbility生命周期
        H_CREATE[onCreate] --> H_WINDOW[onWindowStageCreate]
        H_WINDOW --> H_FORE[onForeground]
        H_FORE --> H_BACK[onBackground]
        H_BACK --> H_DESTROY[onDestroy]
    end
    
    A_CREATE -.->|对应| H_CREATE
    A_RESUME -.->|对应| H_FORE
    A_PAUSE -.->|对应| H_BACK
    A_DESTROY -.->|对应| H_DESTROY
    
    classDef aStyle fill:#4CAF50,stroke:#2E7D32,color:#fff,font-weight:bold
    classDef hStyle fill:#2196F3,stroke:#0A3CC7,color:#fff,font-weight:bold
    classDef mapStyle fill:#FF9800,stroke:#E65100,color:#000,font-weight:bold
    
    class A_CREATE,A_START,A_RESUME,A_PAUSE,A_STOP,A_DESTROY aStyle
    class H_CREATE,H_WINDOW,H_FORE,H_BACK,H_DESTROY hStyle

你看到了吧?Android的7个生命周期方法,在鸿蒙里精简到了5个。那些你写在onResume里的逻辑,要挪到onForeground里。onPause里的逻辑,挪到onBackground里。onStart和onStop呢?大部分情况下,你的逻辑应该放到自定义组件的生命周期里。

代码实战

基础用法:Activity迁移到UIAbility

先看一个最简单的Android Activity:

// Android: 一个典型的Activity
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private val viewModel: MainViewModel by viewModels()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        binding.textView.text = "Hello Android"
        binding.button.setOnClickListener {
            viewModel.loadData()
        }
        
        viewModel.data.observe(this) { data ->
            binding.textView.text = data
        }
    }
    
    override fun onResume() {
        super.onResume()
        viewModel.refresh()
    }
}

迁移到鸿蒙:

// 鸿蒙: UIAbility + 声明式UI
@Entry
@Component
struct MainPage {
  @State message: string = 'Hello HarmonyOS'
  @StorageLink('viewModel') viewModel: MainViewModel = new MainViewModel()
  
  aboutToAppear() {
    // 对应Activity的onResume
    this.viewModel.refresh()
  }
  
  build() {
    Column() {
      Text(this.message)
        .fontSize(24)
        .margin({ top: 20 })
      
      Button('加载数据')
        .onClick(() => {
          this.viewModel.loadData()
        })
        .margin({ top: 20 })
    }
    .width('100%')
    .height('100%')
  }
}

// UIAbility本身很简洁,页面逻辑都在@Component里
export default class MainAbility extends UIAbility {
  onCreate(want, launchParam) {
    // 初始化,对应Android的onCreate
    console.info('MainAbility onCreate')
  }
  
  onWindowStageCreate(windowStage) {
    // 加载页面
    windowStage.loadContent('pages/MainPage', (err, data) => {
      if (err.code) {
        console.error('Failed to load content: ' + JSON.stringify(err))
        return
      }
    })
  }
  
  onForeground() {
    // 对应Android的onResume
    console.info('MainAbility onForeground')
  }
  
  onBackground() {
    // 对应Android的onPause
    console.info('MainAbility onBackground')
  }
}

看出区别了吗?Android里Activity既管生命周期又管UI,鸿蒙里UIAbility只管生命周期,UI全部交给@Component。职责分得更清楚了。

进阶用法:Fragment迁移到自定义组件

Android里Fragment是最让人头疼的东西——生命周期比Activity还复杂,嵌套Fragment更是灾难。

鸿蒙没有Fragment,取而代之的是自定义组件。自定义组件没有Fragment那些乱七八糟的生命周期,只有aboutToAppear和aboutToDisappear。

// Android: Fragment
class UserFragment : Fragment() {
    private var _binding: FragmentUserBinding? = null
    private val binding get() = _binding!!
    private val viewModel: UserViewModel by viewModels()
    
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        _binding = FragmentUserBinding.inflate(inflater, container, false)
        return binding.root
    }
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel.userList.observe(viewLifecycleOwner) { users ->
            binding.recyclerView.adapter = UserAdapter(users)
        }
        viewModel.loadUsers()
    }
    
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null  // 防止内存泄漏
    }
}

迁移到鸿蒙:

// 鸿蒙: 自定义组件,比Fragment简洁太多
@Component
export struct UserComponent {
  @State userList: UserInfo[] = []
  private viewModel: UserViewModel = new UserViewModel()
  
  aboutToAppear() {
    // 对应onViewCreated
    this.viewModel.loadUsers((users: UserInfo[]) => {
      this.userList = users
    })
  }
  
  build() {
    List() {
      ForEach(this.userList, (user: UserInfo) => {
        ListItem() {
          this.UserItem(user)
        }
      }, (user: UserInfo) => user.id.toString())
    }
    .width('100%')
    .height('100%')
  }
  
  @Builder
  UserItem(user: UserInfo) {
    Row() {
      Text(user.name)
        .fontSize(16)
        .fontWeight(FontWeight.Bold)
      Text(user.email)
        .fontSize(14)
        .fontColor('#999999')
    }
    .width('100%')
    .padding(12)
  }
}

没有onCreateView、onViewCreated、onDestroyView的纠缠,没有_binding的空安全噩梦。组件创建时aboutToAppear,销毁时aboutToDisappear,干净利落。

完整示例:Android MVVM迁移到鸿蒙

来一个完整的MVVM架构迁移。Android端:

// Android: ViewModel
class ArticleViewModel : ViewModel() {
    private val _articles = MutableLiveData<List<Article>>()
    val articles: LiveData<List<Article>> = _articles
    
    private val _loading = MutableLiveData<Boolean>()
    val loading: LiveData<Boolean> = _loading
    
    fun loadArticles() {
        viewModelScope.launch {
            _loading.value = true
            try {
                val result = Repository.getArticles()
                _articles.value = result
            } catch (e: Exception) {
                // 错误处理
            } finally {
                _loading.value = false
            }
        }
    }
}

// Android: Activity
class ArticleActivity : AppCompatActivity() {
    private val viewModel: ArticleViewModel by viewModels()
    private lateinit var adapter: ArticleAdapter
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ... 初始化
        
        viewModel.articles.observe(this) { articles ->
            adapter.submitList(articles)
        }
        
        viewModel.loading.observe(this) { isLoading ->
            binding.progressBar.isVisible = isLoading
        }
        
        viewModel.loadArticles()
    }
}

鸿蒙端完整迁移:

// 鸿蒙: ViewModel用@ObservedV2装饰
@ObservedV2
export class ArticleViewModel {
  @Trace articles: Article[] = []
  @Trace loading: boolean = false
  
  private repository: ArticleRepository = new ArticleRepository()
  
  async loadArticles() {
    this.loading = true
    try {
      this.articles = await this.repository.getArticles()
    } catch (e) {
      console.error('加载文章失败: ' + e.message)
    } finally {
      this.loading = false
    }
  }
}

// 鸿蒙: 页面
@Entry
@Component
struct ArticlePage {
  @Local viewModel: ArticleViewModel = new ArticleViewModel()
  
  aboutToAppear() {
    this.viewModel.loadArticles()
  }
  
  build() {
    Column() {
      // 标题栏
      Row() {
        Text('文章列表')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
      .padding({ left: 16, right: 16, top: 12, bottom: 12 })
      
      if (this.viewModel.loading) {
        // 加载状态
        LoadingProgress()
          .width(48)
          .height(48)
          .color('#0A59F7')
      } else {
        // 文章列表
        List() {
          ForEach(this.viewModel.articles, (article: Article) => {
            ListItem() {
              this.ArticleCard(article)
            }
          }, (article: Article) => article.id.toString())
        }
        .width('100%')
        .layoutWeight(1)
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
  
  @Builder
  ArticleCard(article: Article) {
    Column() {
      Text(article.title)
        .fontSize(16)
        .fontWeight(FontWeight.Bold)
        .maxLines(2)
        .textOverflow({ overflow: TextOverflow.Ellipsis })
      
      Text(article.summary)
        .fontSize(14)
        .fontColor('#666666')
        .margin({ top: 8 })
        .maxLines(3)
        .textOverflow({ overflow: TextOverflow.Ellipsis })
      
      Row() {
        Text(article.author)
          .fontSize(12)
          .fontColor('#999999')
        Text(article.date)
          .fontSize(12)
          .fontColor('#999999')
          .margin({ left: 12 })
      }
      .margin({ top: 8 })
    }
    .width('100%')
    .padding(16)
    .backgroundColor(Color.White)
    .borderRadius(8)
    .margin({ left: 16, right: 16, top: 8, bottom: 8 })
  }
}

对比一下:Android的LiveData+ViewModel,到了鸿蒙变成了@ObservedV2+@Trace。观察者模式还是那个观察者模式,只是写法变了。

踩坑与注意事项

坑1:UIAbility不是Activity,别把它当Activity用

Android开发者最容易犯的错误——在UIAbility里写UI逻辑。UIAbility只负责生命周期管理和WindowStage调度,UI逻辑全部放到@Component里。你在onCreate里初始化的那些UI相关的东西,统统挪到aboutToAppear里。

坑2:生命周期对不上,逻辑放错地方

Android的onResume/onPause在鸿蒙里对应onForeground/onBackground,但它们触发的时机不完全一样。onForeground是整个Ability回到前台,不是某个页面获得焦点。页面级别的焦点变化,要用onPageShow/onPageHide。

坑3:Context不一样

Android的Context是个万能钥匙,啥都能干。鸿蒙的Context分了好几种:AbilityContext、ApplicationContext、UIAbilityContext。用错了Context,权限就申请不了,资源就加载不了。

// 正确用法:在UIAbility中获取Context
export default class MainAbility extends UIAbility {
  onCreate(want, launchParam) {
    // 这是UIAbilityContext
    let context = this.context
  }
}

// 在@Component中获取Context
@Entry
@Component
struct MainPage {
  aboutToAppear() {
    // 通过getContext获取
    let context = getContext(this)
  }
}

坑4:后台任务限制更严格

Android的Service可以跑前台服务保活,鸿蒙的后台任务管控严格得多。长时任务需要申请Background Task,而且有明确的场景限制(音乐播放、导航、蓝牙连接等)。你那个"后台默默上传数据"的需求,在鸿蒙上可能要改用延迟任务或者代理提醒。

坑5:权限模型变了

Android的运行时权限申请,到了鸿蒙变成了accesstoken机制。权限分了normal、system_basic、system_core三个等级,你的应用只能申请normal级别的权限。system_basic和system_core需要系统签名,普通应用想都别想。

HarmonyOS 6适配说明

HarmonyOS 6在迁移适配上做了几个重要改进:

  1. UIAbility生命周期进一步简化:新增了onPrepare生命周期回调,在onCreate之前执行,专门处理Ability预加载逻辑。

  2. @ObservedV2替代@Observed:HarmonyOS 6推荐使用@ObservedV2 + @Trace组合,性能比@Observed + @Watch好得多。深度观测不再需要手动设置深度监听层数。

  3. 组件复用能力增强:@Reusable装饰器可以让组件实例被回收复用,长列表场景下性能提升明显。迁移时记得给列表项组件加上@Reusable。

  4. 迁移工具链升级:DevEco Studio 6内置了Android代码迁移助手,能自动识别常见的Android API并给出鸿蒙替代方案。虽然不能100%自动转换,但至少能帮你省掉一半的手动查找工作。

  5. 分布式能力原生支持:HarmonyOS 6的UIAbility天然支持跨设备迁移,你不需要额外写代码就能实现"手机上看到哪,平板接着看"的效果。这是Android完全没有的能力。

总结

Android迁移鸿蒙,核心就三件事:理解架构差异、掌握映射关系、调整编码习惯。

维度 学习难度 使用频率 重要程度
Activity→UIAbility ⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Fragment→@Component ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Service→ExtensionAbility ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐
生命周期映射 ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐
权限模型迁移 ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐
后台任务适配 ⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐

最关键的心态转变:别想着1:1翻译Android代码。鸿蒙的声明式UI天然比Android的命令式UI更简洁,同样的功能,鸿蒙代码量通常只有Android的60%-70%。利用好这个优势,而不是把Android的冗余也搬过来。

下一篇,我们聊聊iOS开发者怎么转鸿蒙——SwiftUI和ArkUI的相似度,可能比你想象的高。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。