草庐IT

『HarmonyOS』Page与AbilitySlice的生命周期

starry陆离 2023-04-12 原文

👨‍🎓作者简介:一位喜欢写作,计科专业大二菜鸟

🏡个人主页:starry陆离

🕒首发日期:2022年8月8日星期一
📚订阅专栏:『HarmonyOS』

🍁每日推荐:牛客网-面试神器

如果文章有帮到你的话记得点赞👍+收藏💗支持一下哦


『HarmonyOS』Page与AbilitySlice的生命周期

系统管理或用户操作等行为均会引起Page实例在其生命周期的不同状态之间进行转换。Ability类提供的回调机制能够让Page及时感知外界变化,从而正确地应对状态变化(比如释放资源),这有助于提升应用的性能和稳健性。

生命周期(百度百科)

生命周期就是指一个对象的生老病死。

​ 生命周期(Life Cycle)的概念应用很广泛,特别是在政治、经济、环境、技术、社会等诸多领域经常出现,其基本涵义可以通俗地理解为 “从摇篮到坟墓”(Cradle-to-Grave的整个过程。对于某个产品而言,就是从自然中来回到自然中去的全过程,也就是既包括制造产品所需要的原材料的采集、加工等生产过程,也包括产品贮存、运输等流通过程,还包括产品的使用过程以及产品报废或处置等废弃回到自然过程,这个过程构成了一个完整的产品的生命周期。

1.Page的生命周期

Page Ability是主要负责页面交互的,所以Page有几个状态:可见,可交互,不可见,销毁等等。每一个状态,都有一个生命周期函数和它对应。Page生命周期的不同状态转换及其对应的回调如下图所示:

1.onStart()

当系统首次创建Page实例时,触发该回调。对于一个Page实例,该回调在其生命周期过程中仅触发一次,Page在该逻辑后将进入INACTIVE状态。开发者必须重写该方法,并在此配置默认展示的AbilitySlice。

@Override
public void onStart(Intent intent) {
    super.onStart(intent);
    super.setMainRoute(MainAbilitySlice.class.getName());
}

2.onActive()

Page会在进入INACTIVE状态后来到前台,然后系统调用此回调。Page在此之后进入ACTIVE状态,该状态是应用与用户交互的状态Page将保持在此状态,除非某类事件发生导致Page失去焦点,比如用户点击返回键或导航到其他Page。当此类事件发生时,会触发Page回到INACTIVE状态,系统将调用onInactive()回调。此后,Page可能重新回到ACTIVE状态,系统将再次调用onActive()回调。因此,开发者通常需要成对实现onActive()和onInactive(),并在onActive()中获取在onInactive()中被释放的资源。

3.onInactive()
**当Page失去焦点时,系统将调用此回调,**此后Page进入INACTIVE状态。开发者可以在此回调中实现Page失去焦点时应表现的恰当行为。

4.onBackground()
如果Page不再对用户可见,系统将调用此回调通知开发者用户进行相应的资源释放,此后Page进入BACKGROUND状态。开发者应该在此回调中释放Page不可见时无用的资源,或在此回调中执行较为耗时的状态保存操作。

5.onForeground()
处于BACKGROUND状态的Page仍然驻留在内存中,当重新回到前台时(重新导航到此Page),系统将先调用onForeground()回调通知开发者,而后Page的生命周期状态回到INACTIVE状态。开发者应当在此回调中重新申请在onBackground()中释放的资源,最后Page的生命周期状态进一步回到ACTIVE状态,系统将通过onActive()回调通知开发者用户。

6.onStop()

系统将要销毁Page时,将会触发此回调函数,通知用户进行系统资源的释放。销毁Page的可能原因包括以下几个方面:

  • 用户通过系统管理能力关闭指定Page,例如使用任务管理器关闭Page。
  • 用户行为触发Page的terminateAbility()方法调用,例如使用应用的退出功能。
  • 配置变更导致系统暂时销毁Page并重建。
  • 系统出于资源管理目的,自动触发对处于BACKGROUND状态Page的销毁。

2.AbilitySlice生命周期

AbilitySlice作为Page的组成单元,其生命周期是依托于其所属Page生命周期的AbilitySlice和Page具有相同的生命周期状态和同名的回调,当Page生命周期发生变化时,它的AbilitySlice也会发生相同的生命周期变化。此外,AbilitySlice还具有独立于Page的生命周期变化,这发生在同一Page中的AbilitySlice之间导航时,此时Page的生命周期状态不会改变。

AbilitySlice生命周期回调与Page的相应回调类似,因此不再赘述。由于AbilitySlice承载具体的页面,开发者必须重写AbilitySlice的onStart()回调,并在此方法中通过setUIContent()方法设置页面,如下所示:

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);

        setUIContent(ResourceTable.Layout_main_layout);
    }

AbilitySlice实例创建和管理通常由应用负责,系统仅在特定情况下会创建AbilitySlice实例。例如,通过导航启动某个AbilitySlice时,是由系统负责实例化;但是在同一个Page中不同的AbilitySlice间导航时则由应用负责实例化。

3.Page与AbilitySlice生命周期关联

当AbilitySlice处于前台且具有焦点时,其生命周期状态随着所属Page的生命周期状态的变化而变化。

当一个Page拥有多个AbilitySlice时,例如:MyAbility下有FooAbilitySlice和BarAbilitySlice,当前FooAbilitySlice处于前台并获得焦点,并即将导航到BarAbilitySlice,在此期间的生命周期状态变化顺序为:

  1. FooAbilitySlice从ACTIVE状态变为INACTIVE状态
  2. BarAbilitySlice则从INITIAL状态首先变为INACTIVE状态,然后变为ACTIVE状态(假定此前BarAbilitySlice未曾启动)。
  3. FooAbilitySlice从INACTIVE状态变为BACKGROUND状态

对应两个slice的生命周期方法回调顺序为:

FooAbilitySlice.onInactive() --> BarAbilitySlice.onStart() --> BarAbilitySlice.onActive() --> FooAbilitySlice.onBackground()

在整个流程中,MyAbility始终处于ACTIVE状态。但是,当Page被系统销毁时,其所有已实例化的AbilitySlice将联动销毁,而不仅是处于前台的AbilitySlice。

4.Page与AbilitySlice生命周期的例子

​ 为了更好地理解Page与AbilitySlice的生命周期,我们将创建一个PageAndAbilitySliceLifeCycle的应用作为演示。

此应用中包含两个Slice,MainAbilitySlicePayAbilitySlice分别代表主页界面和支付界面

我们运行项目首先创建主页界面,主页界面的onStart()onActive()方法分别调用,MainAbilitySlice处于与用户交互的状态

用户点击跳转到支付界面,首先MainAbilitySlice界面失去焦点,进入onInactive()状态;马上创建了一个PayAbilitySlice界面,onStart()方法被调用,紧接着PayAbilitySlice进入onActive()状态,此时用户可见的是支付界面,而MainAbilitySlice调用onBackground()方法,此Slice不再对用户可见,通知开发者释放资源

在这个demo中,系统没有销毁MainAbilitySlice,而是将其存入幕后不再让用户可见,因为我们可以看到日志台并没有打印onStop()方法;也就是说我们每点击一次跳转,就创建一个新的Slice(调用onStart()方法)。

这一次我们不点击跳转了,而是点击虚拟机上的返回按键,可以看到这一次打印了五条日志。首先PayAbilitySlice失去焦点,进入onInactive状态,而MainAbilitySlice从后台资源中重新回到前台,(这里也再次证明了我们的MainAbilitySlice是没有被销毁的)然后就如用户可见的onActive状态;而用户不可见的PayAbilitySlice调用onBackground方法进入后台资源中,最终被onStop()方法销毁,至此PayAbilitySlice度过了它的一个生命周期

5.MainAbilitySlice

package com.hnucm.hmos0501_pageandabilityslicelifecycle.slice;

import com.hnucm.hmos0501_pageandabilityslicelifecycle.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

public class MainAbilitySlice extends AbilitySlice {

    static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MainAbilitySlice"); //MY_MODULE=0x00201
    @Override
    public void onStart(Intent intent) {

        HiLog.info(label, "MainAbilitySlice---->onStart");
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        Button toPayBtn=findComponentById(ResourceTable.Id_toPayBtn);
        toPayBtn.setClickedListener(listener-> present(new PayAbilitySlice(),new Intent()));
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        HiLog.info(label, "MainAbilitySlice---->onInactive");
    }

    @Override
    protected void onBackground() {
        super.onBackground();

        HiLog.info(label, "MainAbilitySlice---->onBackground");

    }

    @Override
    protected void onStop() {
        super.onStop();
        HiLog.info(label, "MainAbilitySlice---->onStop");

    }

    @Override
    public void onActive() {
        super.onActive();
        HiLog.info(label,  "MainAbilitySlice---->onActive");
    }
    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
        HiLog.info(label, "MainAbilitySlice---->onForeground");
    }
}

6.PayAbilitySlice

package com.hnucm.hmos0501_pageandabilityslicelifecycle.slice;

import com.hnucm.hmos0501_pageandabilityslicelifecycle.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

public class PayAbilitySlice extends AbilitySlice {

    static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00201, "PayAbilitySlice"); //MY_MODULE=0x00201

    @Override
    public void onStart(Intent intent) {

        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_pay);

        HiLog.info(label, "PayAbilitySlice---->onStart");


        Button backMainBtn=findComponentById(ResourceTable.Id_backMainBtn);
        backMainBtn.setClickedListener(listener-> present(new MainAbilitySlice(),new Intent()));
    }

    @Override
    public void onActive() {
        super.onActive();
        HiLog.info(label, "PayAbilitySlice---->onActive");

    }

    @Override
    protected void onInactive() {
        super.onInactive();
        HiLog.info(label, "PayAbilitySlice---->onInactive");

    }

    @Override
    protected void onBackground() {
        super.onBackground();
        HiLog.info(label, "PayAbilitySlice---->onBackground");


    }

    @Override
    protected void onStop() {
        super.onStop();
        HiLog.info(label, "PayAbilitySlice---->onStop");

    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
        HiLog.info(label, "PayAbilitySlice---->onForeground");

    }
}

🍁每日推荐:牛客网-面试神器

有关『HarmonyOS』Page与AbilitySlice的生命周期的更多相关文章

  1. ruby - caches_page :all - 2

    有什么方法可以告诉Rails3在给定的Controller中缓存所有页面,而不必在调用caches_page时列出所有页面?我尝试了caches_page:all,但它不起作用。 最佳答案 有点像实现的错误,但我刚刚尝试过它并且它适用于Rails3.0.6:caches_page:except=>[] 关于ruby-caches_page:all,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/que

  2. HarmonyOS原子化服务开发相关术语 - 2

    术语中文解释Ability原子化服务帮助用户完成任务的原子化服务,和用户的意图进行关联。Fulfillment服务履行通过图标,卡片,语音等形式呈现用户意图。开发者通过接口的方式,处理用户意图,返回内容。Intent意图用于表达用户想要达成的目标或完成的任务。HUAWEIAssistant智能助手“无微不智”的个人助手,通过不断的学习用户的使用习惯,不断的为用户提供贴心的精准的便捷的个性化服务。AISearch全局搜索用户可快速搜索关键词,与之匹配的原子化服务则会出现在搜索结果中。SmartService智慧服务用户订阅原子化服务,在到达特定触发条件(时间、地点、事件)后,卡片推送至用户智能助

  3. ruby-on-rails - Ruby on Rails : if current page? 是主页,不显示表单 - 2

    我不想显示表单,但前提是当前页面不是主页这是我目前所拥有的...我有我的路线设置:root'projects#index'我的看法:'projects',:action=>'index'))%>showsomestuff如果url是localhost:3000/projects,则不会显示但是它显示了它的localhost:3000所以我需要以某种方式确保它不会显示主页。另外,我有主页的搜索参数,但我仍然不想显示它是否像localhost:3000/projects?search=blahblahblah 最佳答案 使用root_p

  4. ruby-on-rails - rails expire_page 没有删除缓存的文件 - 2

    我有一个具有页面缓存的ControllerAction,我制作了一个清扫程序,它使用Controller和指定的Action调用expire_page...Controller操作呈现一个js.erb模板,所以我试图确保expire_page删除public/javascripts中的.js文件,但它没有这样做。classJavascriptsController"javascripts",:action=>"lol",:format=>'js')endend...所以,我访问javascripts/lol.js并呈现我的模板。我验证了public/javascripts/lol.js

  5. ruby-on-rails - 目录 : Forgot Password & Sign In - in same page - 2

    我正在尝试将忘记密码字段与登录页面放在一起,但如果用户未注册(并且不在应用程序数据库中),则它会重定向到原始设计的忘记密码页面并出现错误(http://localhost:3000/用户/密码)。如何使错误出现在与登录页面(http://localhost:3000/users/sign_in)相同的页面中?在app/views/devise/sessions/new.html.erb文件中ForgotPasswordEntertheemailyousignedupwith所以有一个javascript链接,如果用户忘记了他们的登录凭据,输入字段将显示在该链接上。

  6. ruby - 在 Ruby 中查找周期和范围集差异的有效方法 - 2

    我在Ruby中有很多时间范围:period=Time.parse('8:00am')..Time.parse('8:00pm')incidents=[Time.parse('7:00am')..Time.parse('9:00am'),Time.parse('1:00pm')..Time.parse('3:00pm'),Time.parse('1:30pm')..Time.parse('3:30pm'),Time.parse('7:00pm')..Time.parse('9:00pm'),]我正试图在这段时间内获得一系列无事件block。对于以上内容:[Time.parse('9:00

  7. ruby-on-rails - ruby rails : How do you list the partial paths that are rendered for a page? - 2

    我希望列出为我的应用程序中的每个页面呈现的部分内容。例如,当显示app/tasks/index.html.erb页面时,我想向用户显示如下内容:Partialsrenderedforthispage:tasks/_list.html.erbtasks/_button.html.erbtasks/_navigation.html.erb在RubyonRails中有什么方法可以做到这一点吗? 最佳答案 是的,在Rails中完全可以做到这一点!正如bdares在他的评论中指出的那样,用于模板渲染的行出现在日志中。但他们最初是如何到达那里的

  8. ruby - 如何在 Jekyll 中没有 html 扩展名的情况下使用 page.url 链接到页面? - 2

    我正在用Jekyll构建一个网站。为了删除帖子中的html扩展名,我将以下内容添加到_config.ymlpermalink:/kb/:title为了从页面中删除html扩展名,我为每个页面创建了文件夹,并在每个页面文件夹中放置了一个index.html文件。现在帖子和页面在没有html扩展名的情况下也能正常工作,但是当我使用page.url链接到页面时,它会返回整个链接(/kb/index.html)而不仅仅是/kb。我可以使用什么变量链接到没有html扩展名的页面? 最佳答案 {{page.url}}返回的值反射(reflect

  9. ruby-on-rails - 有没有一种简单的方法可以在 Passenger 的请求周期之外运行垃圾收集? - 2

    unicorn有OobGC可用于在一定数量的请求后运行GC.start的机架中间件。PhusionPassenger中有类似的东西吗? 最佳答案 PhusionPassenger4正式引入了带外垃圾回收机制。它比Unicorn更灵活,允许任意工作,而不仅仅是垃圾收集。http://blog.phusion.nl/2013/01/22/phusion-passenger-4-technology-preview-out-of-band-work/ 关于ruby-on-rails-有没有一种

  10. ruby - 如何将变量传递给 capybara 中的 page.executescript() - 2

    我需要在javascript中传递要通过capybara中的excute_script方法执行的变量。我无法将变量传递给它。请任何人帮助我。例子:@idd="sample"txt=page.execute_script('varuser_id=${@idd};returnuser_id;')putstxt我希望打印文本示例,但我遇到了Java脚本错误。 最佳答案 我认为问题出在${};你必须使用#{};尝试:page.execute_script("varuser_id='#{@idd}';returnuser_id;")

随机推荐