HarmonyOS开发实战:自定义装饰器实现Lifecycle组件

141 篇文章 0 订阅
131 篇文章 0 订阅

1. 背景

在鸿蒙实际开发中,为了防止内存泄露我们有以下写法。需要手动在aboutToDisappear 中反注册,或者执行一段逻辑。此时我们会有点怀念Android JetPack中的Lifecycle 组件。

1.1 事件订阅-页面关闭取消监听键盘高度变化

import { Utils } from '@android/utilcode'
@Component
struct Test {
  private onKeyboardHeightChange = (height: number) => {
    //键盘高度变化
    console.log(`键盘高度${height}`)
  }

  /**
   * 注册键盘高度监听
   */
  aboutToAppear() {
    Utils.getMainWindow()?.on('keyboardHeightChange', this.onKeyboardHeightChange)
  }

  //取消注册键盘高度监听
  aboutToDisappear(): void {
    Utils.getMainWindow()?.off('keyboardHeightChange', this.onKeyboardHeightChange)
  }
  build() {
  }
}

1.2 网络请求-页面关闭取消未完成的网络请求

import { rcp } from "@kit.RemoteCommunicationKit";
import { BusinessError } from '@kit.BasicServicesKit';

@Component
struct Test {
  private session?: rcp.Session;

  build() {
    Button('发起网络请求').onClick(() => {
      this.session = rcp.createSession();
      this.session.get("https://wanandroid.com/harmony/index/json").then((response) => {
        console.info(`${response}`);
      }).catch((err: BusinessError) => {
        console.error(`err: err code is ${err.code}, err message is ${err.message}`);
      });
    })
  }

  //取消未完成的网络请求
  aboutToDisappear(): void {
    this.session?.cancel()
    this.session?.close()
  }
}

2. 使用TS自定义装饰器封装 Lifecycle

2.1 先创建一个生命周期管理类Lifecycle.ets

import { ArrayList } from '@kit.ArkTS';


/**
 * 生命周期状态
 * @author Tanranran
 * @date 2024/6/5 23:45
 * @description
 */
export enum LifecycleState {
  ToAppear,
  PageShow,
  PageHide,
  ToDisappear,
}

/**
 * 生命周期包装类
 * @author Tanranran
 * @date 2024/6/5 23:45
 * @description
 */
export class Lifecycle {
  private mObserverList: ArrayList<(state: LifecycleState) => void> | null = new ArrayList();

  /**
   * @Component
   * 组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。
   */
  aboutToAppear() {
    this.dispatchEvent(LifecycleState.ToAppear)
  }

  /**
   * @Entry
   * 页面每次显示时触发一次,包括路由过程、应用进入前台等场景。
   */
  onPageShow() {
    this.dispatchEvent(LifecycleState.PageShow)
  }

  /**
   * @Entry
   * 页面每次隐藏时触发一次,包括路由过程、应用进入后台等场景。
   */
  onPageHide() {
    this.dispatchEvent(LifecycleState.PageHide)
  }

  /**
   * @Component
   * aboutToDisappear函数在自定义组件析构销毁之前执行
   */
  aboutToDisappear() {
    this.dispatchEvent(LifecycleState.ToDisappear)
  }

  /**
   * 向所有观察者分发状态
   * @param state
   */
  private dispatchEvent(state: LifecycleState) {
    this.mObserverList?.forEach((callback: (state: LifecycleState) => void) => {
      callback(state)
    });
  }

  /**
   * 添加观察者
   * @param callback
   */
  addObserver(callback: (state: LifecycleState) => void) {
    this.mObserverList?.add(callback)
  }

  /**
   * 移除观察者
   * @param callback
   */
  removeObserver(callback: (state: LifecycleState) => void) {
    this.mObserverList?.remove(callback)
  }

  /**
   * 释放所有观察者
   */
  release() {
    this.mObserverList?.clear()
    this.mObserverList = null
  }
}

2.2 再创建一个和组件生命周期绑定的自定义装饰类 LifecycleEvent.ts

export function LifecycleEvent(target: any, propertyKey: string | any) {
  let value: any;
  const getter = () => value;
  const setter = function (newValue: any) {
    value = newValue;
  };
  Object.defineProperty(target, propertyKey, {
    get: getter,
    set: setter,
    enumerable: true,
    configurable: true,
  });

  if (target.rerender) {
    if (target.aboutToAppear) {
      let oldFunction = target.aboutToAppear
      function appear() {
        oldFunction.call(this)
        target[propertyKey].aboutToAppear()
      }
      target.aboutToAppear = appear
    } else {
      target.aboutToAppear = () => {
        target[propertyKey].aboutToAppear()
      }
    }

    if (target.onPageShow) {
      let oldFunction = target.onPageShow

      function pageShow() {
        target[propertyKey].onPageShow()
        oldFunction.call(this)
      }

      target.onPageShow = pageShow
    } else {
      target.onPageShow = () => {
        target[propertyKey].onPageShow()
      }
    }

    if (target.onPageHide) {
      let oldFunction = target.onPageHide

      function pageHide() {
        target[propertyKey].onPageHide()
        oldFunction.call(this)
      }

      target.onPageHide = pageHide
    } else {
      target.onPageHide = () => {
        target[propertyKey].onPageHide()
      }
    }

    if (target.aboutToDisappear) {
      let oldFunction = target.aboutToDisappear
      function disappear() {
        target[propertyKey].aboutToDisappear()
        target[propertyKey].release()
        oldFunction.call(disappear.prototype.caller)
      }
      target.aboutToDisappear = disappear
    } else {
      target.aboutToDisappear = () => {
        target[propertyKey].aboutToDisappear()
        target[propertyKey].release()
      }
    }
  }
}

3.使用TS自定义装饰器封装,自动取消页面中未完成的网络请求

@LifecycleEvent 声明的Lifecycle 会自动绑定@Component 的aboutToDisappear 生命周期,当组件销毁时,会回调 Lifecycle.ets 中的mObserverList集合。所有注册了addObserver 的监听均会收到生命周期变化的回调

3.1 封装和页面生命周期绑定的网络请求帮助类

import { rcp } from "@kit.RemoteCommunicationKit";
import { Lifecycle } from '@android/utilcode';
import { LifecycleState } from '@android/utilcode/src/main/ets/lifecycle/Lifecycle';

/**
 * @author Tanranran
 * @date 2024/6/17 17:48
 * @description
 */
export class HttpHelper {
  static Get(url: string, lifecycle: Lifecycle):Promise<rcp.Response>{
    let session = rcp.createSession();
    lifecycle.addObserver((state: LifecycleState) => {
      if (state == LifecycleState.ToDisappear) {
        session.cancel()
        session.close()
      }
    })
    return session.get(url);
  }
}

3.2 使用带有生命周期绑定的网络请求帮助类

import { HttpHelper } from './HttpHelper';
import { Lifecycle, LifecycleEvent } from '@android/utilcode';

@Component
struct Test {
  @LifecycleEvent lifecycle: Lifecycle = new Lifecycle()

  build() {
    Button('发起网络请求').onClick(() => {
      HttpHelper.Get('https://wanandroid.com/harmony/index/json', this.lifecycle)
    })
  }
}

4. 如果想用现成的可以直接使用远程库

 

自定义组件生命周期绑定装饰器,可通过以下方式自动绑定自定义组件的生命周期,使用方法和Android中的Lifecycle类似 无需关注lifecycle的释放,自定义组件aboutToDisappear时,lifecycle会自动释放

使用场景:比如页面关闭后,当前页面上的未请求完毕网络请求自动取消

注:目前仅支持aboutToAppear【Component】、onPageShow【Entry】、onPageHide【Entry】、aboutToDisappear【Component】,navigation 比较特殊,目前暂未找到合适的时机

import {Lifecycle, LifecycleEvent } from '@android/utilcode';
@Component
@Preview
export struct TestFragment {
    @LifecycleEvent lifecycle: Lifecycle = new Lifecycle()
    aboutToAppear(): void {
      this.lifecycle.addObserver((state: LifecycleState) => {
        //此处即可
        console.log("状态" + state)
      })
    }
}

最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?但是又不知道从哪里下手,而且学习时频繁踩坑,最终浪费大量时间。所以本人整理了一些比较合适的鸿蒙(HarmonyOS NEXT)学习路径和一些资料的整理供小伙伴学习

点击领取→纯血鸿蒙Next全套最新学习资料希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取~~

一、鸿蒙(HarmonyOS NEXT)最新学习路线

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)…等技术知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

二、HarmonyOS Next 最新全套视频教程

三、《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

四、大厂面试必问面试题

五、鸿蒙南向开发技术

六、鸿蒙APP开发必备


完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

                        

  • 17
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值