为有牺牲多壮志,敢教日月换新天。

UIAbility组件基础

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤博客园地址:为敢技术(https://www.cnblogs.com/strengthen/ 
➤GitHub地址:https://github.com/strengthen
➤原文地址: https://www.cnblogs.com/strengthen/p/18473894
➤如果链接不是为敢技术的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ 

一、什么是UIAbility
UIAbility是一种包含用户界面的应用组件,用于和用户进行交互,UIAblility是系统调度的单元,提供窗口用于界面绘制。

1、进程是资源分配的最小单位,线程是CPU调度的最小单位。线程是进程中的实体,一个进程可以拥有多个线程,一个线程必须有一个父进程。线程不拥有系统资源,只有运行必须的一些数据结构。

进程是系统资源分配的基本单位(可以看成是资源的容器),线程是调度的基本单位。

(1)、线程只由相关堆栈(系统栈或用户栈)寄存器和线程控制表TCB组成。寄存器可被用来存储线程内的局部变量,但不能存储其他线程的相关变量。

(2)、进程为应用程序运行实例,是应用程序的一次动态执行,进程是由进程控制块、程序段、数据段3部分组成,一个进程可以包含若干线程,使用线程可以实现应用程序同时做几件事并且互相不干扰,进程是操作系统进程资源分配的单位。

(3)、扩展资料:

  • 线程是进程中的实体,一个进程可以拥有多个线程,一个线程必须有一个父进程。线程不拥有系统资源,只有运行必须的一些数据结构;
  • 它与父进程的其它线程共享该进程所拥有的全部资源。线程可以创建和撤消线程,从而实现程序的并发执行。一般,线程具有就绪、阻塞和运行三种基本状态。
  • 在多中央处理器的系统里,不同线程可以同时在不同的中央处理器上运行,甚至当它们属于同一个进程时也是如此。大多数支持多处理器的操作系统都提供编程接口来让进程可以控制自己的线程与各处理器之间的关联度(affinity)。
  • 有时候,线程也称作轻量级进程。就象进程一样,线程在程序中是独立的、并发的执行路径,每个线程有它自己的堆栈、自己的程序计数器和自己的局部变量。但是,与分隔的进程相比,进程中的线程之间的隔离程度要小。它们共享内存、文件句柄和其它每个进程应有的状态。
应用程序有几种交互形式:
2、方式一:点击桌面图标进入应用。例如在桌面上点击图库图标,来拉起图库应用。看到的图库应用就是基于UIAbility实现的一个应用实例。

3、方式二:还可以从最近的任务列表中找到该应用。看到的任务列表中的应用任务,也都是基于UIAbility实现的一个应用实例。每一个UIAbility实例都对应于一个最近任务列表中的任务。UIAbility作为系统调度的单元,提供窗口用于界面绘制。以图库应用为例,在这个窗口上照片浏览页就是用户看到的绘制内容。

二、UIAbility内的页面创建
每个UIAbility中可能包含多个页面,如何在UIAbility中创建页面呢?
在工程pages目录下,右键新建一个page,命名为Second.ets,如果选择新建的是一个ArkTS File,就需要在resources/base/profile目录下的main_pages.json文件中手动配置路由。

三、页面间的跳转和数据传递
在Index页面中,首先导入路由模块,通过调用router.pushUrl()方法,将url指定为需要跳转的Second页面路径即可。

通常,在进行页面跳转时,会涉及到参数的传递,在上述页面跳转的基础上,调用router.pushUrl()方法的时候,可以传入一个自定义参数params。

import { router } from '@kit.ArkUI';
import CommonConstants from '../common/constants/CommonConstants';
import Logger from '../common/utils/Logger';

const TAG = '[IndexPage]';
class routerParams {
  src:string
  constructor(str:string) {
    this.src = str
  }
}

/**
 * The IndexPage is the entry point of the application.
 */
@Entry
@Component
struct IndexPage {
  @State message: string = CommonConstants.INDEX_MESSAGE;

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(CommonConstants.FONT_SIZE)
          .fontWeight(FontWeight.Bold)
        Blank()
        Button($r('app.string.next'))
          .fontSize(CommonConstants.BUTTON_FONT_SIZE)
          .width(CommonConstants.BUTTON_WIDTH)
          .height(CommonConstants.BUTTON_HEIGHT)
          .backgroundColor($r('app.color.button_bg'))
          .onClick(() => {
            router.pushUrl({
              url: CommonConstants.SECOND_URL,
              params: new routerParams(CommonConstants.SECOND_SRC_MSG)
            }).catch((error:Error) => {
              Logger.info(TAG, 'IndexPage push error' + JSON.stringify(error));
            });
          })
      }
      .width(CommonConstants.FULL_WIDTH)
      .height(CommonConstants.LAYOUT_HEIGHT)
    }
    .height(CommonConstants.FULL_HEIGHT)
    .backgroundColor($r('app.color.page_bg'))
  }
}

在Second页面中,如何接收刚刚传递的自定义参数呢?首先同样导入路由依赖模块,通过调用router.getParams()方法,获取Index页面传递过来的自定义参数。获取传递过来的src参数,并进行页面刷新展示。在Index页面中,点击“Next”后,即可从Index页面跳转到Second页面,Second页面中接收到参数后即可展示数据。

import { router } from '@kit.ArkUI';
import CommonConstants from '../common/constants/CommonConstants';

class routerParams {
  src:string = ''
}
/**
 * The SecondPage is the router push page.
 */
@Entry
@Component
struct SecondPage {
  @State message: string = CommonConstants.SECOND_MESSAGE;
  @State params: routerParams = router.getParams() as routerParams
  @State src: string = this.params.src;

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(CommonConstants.FONT_SIZE)
          .fontWeight(FontWeight.Bold)
        Text(this.src)
          .fontSize(CommonConstants.PARAMS_FONT_SIZE)
          .opacity(CommonConstants.PARAMS_OPACITY)
        Blank()
        Button($r('app.string.back'))
          .fontSize(CommonConstants.BUTTON_FONT_SIZE)
          .width(CommonConstants.BUTTON_WIDTH)
          .height(CommonConstants.BUTTON_HEIGHT)
          .backgroundColor($r('app.color.button_bg'))
          .onClick(() => {
            router.back();
          })
      }
      .width(CommonConstants.FULL_WIDTH)
      .height(CommonConstants.LAYOUT_HEIGHT)
    }
    .height(CommonConstants.FULL_HEIGHT)
    .backgroundColor($r('app.color.page_bg'))
  }
}

当我们在Second页面中完成了一些功能操作之后,希望能返回到Index页面时,可以在Second页面中,添加一个Button按钮,并绑定一个onClick()事件,在onClick()事件中,调用router.back()方法,即可实现返回上一个页面的功能。

四、UIAbility的生命周期
1、当用户打开、切换和返回到对应应用时,应用中的UIAbility实例会在其生命周期的不同状态之间进行切换。UIAbility类提供了一系列回调,通过这些回调可以知道当前UIAbility实例的某个状态放生改变,会经过UIAbility实例的创建和销毁,或者UIAbility实例发生了前后台的状态切换,
上方进入程序的两种方式:
(1)、从桌面点击图库应用的图标到启动图库应用,应用的状态经过了从创建到前台展示的状态变化。
(2)、回到桌面,从最近任务列表切换回到图库应用,应用到状态经历了从后台到前台展示的状态变化。

除了前后台切换外,其实在UIAbility的使用过程中,会有多种生命周期状态,掌握UIAbility的生命周期,对于应用的开发非常重要。

总的来说,UIAbility的生命周期包括:Create、Foreground、Background、Destroy。

另外,WindowStageCreate和WindowStageDestroy是UIAbility中管理UI功能的两个生命周期回调。

每个UIAblility中都包含了一个Context属性,UIAbility功能主要是处理生命周期,其余操作UIAbility的方法,例如:startUIAbility()、connectUIAbility()、terminateSelf()这些都是在UIAbilityContext中实现的。

2、Create状态是在应用加载过程中,UIAbility实例创建完成时触发,系统会调用onCreate()回调,可以在该回调中进行应用初始化,例如:变量定义、资源加载等用于后续的UI展示。

3、UIAbility实例创建完成之后,在进入Foreground之前,系统会创建一个WindowStage,在WindowStage创建完成后,会进入onWindowStageCreate()回调,在该回调中,可以通过loadContent()的方法,设置应用需要加载的页面,并根据需要订阅WindowStage的事件,例如:获焦/失焦、可见/不可见。

4、Foreground状态:UIAbility实例切换至前台时触发,对应于onForeground()回调。onForeground()回调在UIAbility的UI可见之前,例如:UIAbility切换至前台时触发,可以在onForeground()回调中申请系统需要的资源,

Background状态:UIAbility实例切换至后台时触发,对应于onBackground()回调。onBackground()回调在UIAbility的UI完全不可见之后,例如:UIAbility切换至后台时触发,可以在onBackground()回调中释放UI不可见时无用的资源。

5、在UIAbility实例销毁之前,则会先进入onWindowStageDestroy()回调,可以在该回调中释放UI资源,例如:在onWindowStageDestroy()中,注销获焦/失焦等WindowStage事件。

6、当用户从最近任务列表关闭任务时,可以销毁当前的UIAbility实例,此时会触发Destroy状态,如果想进行资源释放或数据保存,可以在onDestroy()回调中实现对应的逻辑。

五、Codelabs实践:《UIAbility内页面的跳转》这个Codelab:实现了UIAbility内两个页面之间的跳转和数据传递,具体的代码可以到Codelabs中进行进一步的学习。下载链接:PagesRouter.zip

 

posted @ 2024-10-18 11:21  为敢技术  阅读(31)  评论(0编辑  收藏  举报