#HarmonyOS NEXT体验官#手把手教你自定义装饰器实现Android中的Lifecycle组件 原创

冉冉同学
发布于 2024-8-1 11:06
浏览
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. 如果想用现成的可以直接使用远程库

https://ohpm.openharmony.cn/#/cn/detail/@android%2Futilcode

自定义组件生命周期绑定装饰器,可通过以下方式自动绑定自定义组件的生命周期,使用方法和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)
      })
    }
}

5. 另外分享一篇关于鸿蒙状态管理装饰器的实现的文章

https://juejin.cn/post/7380357384776073266

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
收藏
回复
举报
回复
    相关推荐