文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

ActiveData在HarmonyOS中的原理分析和运用

2024-12-02 23:22

关注

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

在讲解ActiveData实现原理之前,我们有必要先了解一下两个重要的类Lifecycle以及DataObserver,这两个类在ActiveData整个运行过程中扮演了非常重要的角色。

ActiveData作用和特点

ActiveData是一个具有感知生命周期能力变化的数据通知类组件,非常适合在一些对数据同步性较高的场景下使用,它具有以下三个特点。

基于观察者模式:

ActiveData是一个持有可被观察数据的类,ActiveData需要一个观察者对象,一般是DataObserver类的具体实现。

感知生命周期:

ActiveData具有生命周期感知能力,目前ActiveData具有两种通知模式,一种是Ability/AbilitySlice生命周期是活跃(ACTIVE)状态时才更新数据,另一种是Ability/AbilitySlice生命周期处于任何存活状态(即只要没有被销毁)都可以更新数据。

自动解除数据订阅:

ActiveData必须配合实现了Lifecycle的对象使用。当Ability/AbilitySlice被销毁(STOP状态)后,会自动解除订阅,这在一定程度上可以避免内存泄漏等问题。

实践

基础用法

  1. public class MainAbilitySlice extends AbilitySlice { 
  2.     private ActiveData activeData; 
  3.  
  4.     private Text mText; 
  5.  
  6.     private final DataObserver dataObserver = new DataObserver() { 
  7.         @Override 
  8.         public void onChanged(String s) { 
  9.             mText.setText(s); 
  10.         } 
  11.     }; 
  12.  
  13.     @Override 
  14.     public void onStart(Intent intent) { 
  15.         super.onStart(intent); 
  16.         super.setUIContent(ResourceTable.Layout_ability_main); 
  17.         activeData = new ActiveData<>(); 
  18.         dataObserver.setLifecycle(getLifecycle()); 
  19.  
  20.         mText = (Text) findComponentById(ResourceTable.Id_text_helloworld); 
  21.  
  22.         subscribe(); 
  23.     } 
  24.  
  25.     private void subscribe() { 
  26.         activeData.addObserver(dataObserver, true); 
  27.     } 
  28.  
  29.     @Override 
  30.     public void onActive() { 
  31.         super.onActive(); 
  32.         activeData.setData("New Hello World"); 
  33.     } 

运行之后的截图:


从运行结果可以看出,setData调用后会立即触发onChanged回调方法

主线程手动调用

  1. // 添加如下代码测试DataObserver的onChanged方法是否会执行 
  2. findComponentById(ResourceTable.Id_button) 
  3.                 .setClickedListener(component -> activeData.setData("I Love China")); 

 运行结果如下:


从运行结果我们可以看到,onChanged方法会一直触发,并不会因为值相同而不执行,虽然暂时看不了鸿蒙源码,但我们可以大胆猜测,鸿蒙底层维护了一个类似于版本号的标记,每次setData,该标记会自动+1,从而通过此版本号来判断data是否有变化,进而决定是否触发onChanged回调方法。

子线程调用

  1. @Override 
  2.    public void onActive() { 
  3.        super.onActive(); 
  4.        new Thread(() -> activeData.setData("New Hello World")).start(); 
  5.    }  

运行后发现没有问题,可以正常调用,说明setData方法可以在子线程调用。

  1. public class MainAbilitySlice extends AbilitySlice { 
  2.     private ActiveData activeData; 
  3.     private ActiveData activeData2; 
  4.  
  5.     private Text mText; 
  6.  
  7.     private final DataObserver dataObserver = new DataObserver() { 
  8.         @Override 
  9.         public void onChanged(String s) { 
  10.             mText.setText(s); 
  11.             System.out.println("ActiveData:---onChange:"+s); 
  12.         } 
  13.     }; 
  14.  
  15.     private final DataObserver dataObserver2 = new DataObserver() { 
  16.         @Override 
  17.         public void onChanged(String s) { 
  18.             mText.setText(s); 
  19.             System.out.println("ActiveData:---onChange:"+s); 
  20.         } 
  21.     }; 
  22.  
  23.     @Override 
  24.     public void onStart(Intent intent) { 
  25.         super.onStart(intent); 
  26.         super.setUIContent(ResourceTable.Layout_ability_main); 
  27.         activeData = new ActiveData<>(); 
  28.         activeData2 = new ActiveData<>(); 
  29.  
  30.         dataObserver.setLifecycle(getLifecycle()); 
  31.         dataObserver2.setLifecycle(getLifecycle()); 
  32.  
  33.         mText = (Text) findComponentById(ResourceTable.Id_text_helloworld); 
  34.         findComponentById(ResourceTable.Id_button) 
  35.                 .setClickedListener(component -> activeData.setData("I Love China")); 
  36.  
  37.         findComponentById(ResourceTable.Id_addObserver_true).setClickedListener(component -> { 
  38.             System.out.println("ActiveData:-------------"); 
  39.             Intent intent1 = new Intent(); 
  40.             Operation operation = new Intent.OperationBuilder() 
  41.                     .withDeviceId(""
  42.                     .withBundleName(getBundleName()) 
  43.                     .withAbilityName(SecondAbility.class.getName()) 
  44.                     .build(); 
  45.  
  46.             intent1.setOperation(operation); 
  47.             startAbility(intent1); 
  48.             // 此处是为了验证Ability在inActive状态的值的变化情况 
  49.             new EventHandler(EventRunner.getMainEventRunner()).postTask(() -> activeData.setData("New Hello World"), 2000); 
  50.         }); 
  51.  
  52.         findComponentById(ResourceTable.Id_addObserver_false).setClickedListener(component -> { 
  53.             System.out.println("ActiveData:-------------"); 
  54.             Intent intent1 = new Intent(); 
  55.             Operation operation = new Intent.OperationBuilder() 
  56.                     .withDeviceId(""
  57.                     .withBundleName(getBundleName()) 
  58.                     .withAbilityName(SecondAbility.class.getName()) 
  59.                     .build(); 
  60.  
  61.             intent1.setOperation(operation); 
  62.             startAbility(intent1); 
  63.             // 此处是为了验证Ability在inActive状态的值的变化情况 
  64.             new EventHandler(EventRunner.getMainEventRunner()).postTask(() -> activeData2.setData("New Hello World"), 2000); 
  65.         }); 
  66.  
  67.         subscribe(); 
  68.     } 
  69.  
  70.     private void subscribe() { 
  71.         activeData.addObserver(dataObserver, true); 
  72.         activeData2.addObserver(dataObserver, false); 
  73.     } 
  74.  
  75.     @Override 
  76.     public void onActive() { 
  77.         super.onActive(); 
  78.         System.out.println("ActiveData:---onActive"); 
  79.     } 
  80.  
  81.     @Override 
  82.     protected void onInactive() { 
  83.         super.onInactive(); 
  84.         System.out.println("ActiveData:---onInactive"); 
  85.     } 
  86.  
  87.     @Override 
  88.     protected void onBackground() { 
  89.         super.onBackground(); 
  90.         System.out.println("ActiveData:---onBackground"); 
  91.     } 
  92.  
  93.     @Override 
  94.     public void onForeground(Intent intent) { 
  95.         super.onForeground(intent); 
  96.     System.out.println("ActiveData:---onForeground"); 
  97.     } 

运行效果如下: 

从以上运行结果,可以看出addObserver(dataObserver, true/false)方法的特点,当为true是表示无论Ability/AbilitySlice处于任何生命周期状态,均会触发onChanged回调方法,当为false时表示Ability/AbilitySlice只有处于ACTIVE状态时才会触发onChanged方法。

总结

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

来源:鸿蒙社区内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯