【HarmonyOS NEXT】getLastWindow获取到的对象属性为空导致异常报错

175 阅读2分钟

【HarmonyOS NEXT】getLastWindow获取到的对象属性为空导致异常报错

一、问题背景

因为getLastWindow获取最顶层窗口对象是异步操作,通过callback或者await或者then回调拿到对象,在性能方面会有限制,导致拿到的最顶层对象可能已经被销毁了,所以回调操作对象属性为空会导致异常报错

二、解决方案:

因为getLastWindow底层原因,需要经过查找获取实例,一定程度上会有性能损耗,可能会出现某些情况下,窗口状态还没切换的情况。对此类场景的同步要求较高情况下,可以使用windowStage.getMainWindowSync的同步方式获取窗口实例。

三、DEMO示例:

import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct SubWinPage {
  private TAG: string = "SubWinPage";
  private sub_windowClass: window.Window | null = null;

   aboutToAppear() {
    this.showSubWindow()
     setTimeout(()=>{
       try {
         this.destroySubWindow();
         // 此时会有异常情况
         window.getLastWindow(getContext()).then((win)=>{
           console.error(this.TAG, 'win:' + JSON.stringify(win));
           let height = win.getWindowDecorHeight();
           console.error(this.TAG, 'height:' + height);
         })
         // 替换为
         let windowStage_:  window.WindowStage = globalThis.mWindowStage;
         let win = windowStage_.getMainWindowSync();
         let height = win.getWindowDecorHeight();
       }catch (e){
         console.error(this.TAG, 'e:' + JSON.stringify(e));
       }
     },1000)
  }

  private showSubWindow() {
    console.log(this.TAG, 'showSubWindow start');
    let windowStage_:  window.WindowStage = globalThis.mWindowStage;
    // 1.创建应用子窗口。
    if (windowStage_ == null) {
      console.error(this.TAG, 'Failed to create the subwindow. Cause: windowStage_ is null');
    }
    else {
      windowStage_.createSubWindow("mySubWindow", (err: BusinessError, data) => {
        let errCode: number = err.code;
        if (errCode) {
          console.error(this.TAG, 'Failed to create the subwindow. Cause: ' + JSON.stringify(err));
          return;
        }
        this.sub_windowClass = data;
        console.info(this.TAG, 'Succeeded in creating the subwindow. Data: ' + JSON.stringify(data));
        // 2.子窗口创建成功后,设置子窗口的位置、大小及相关属性等。
        this.sub_windowClass.moveWindowTo(300, 300, (err: BusinessError) => {
          let errCode: number = err.code;
          if (errCode) {
            console.error(this.TAG, 'Failed to move the window. Cause:' + JSON.stringify(err));
            return;
          }
          console.info(this.TAG, 'Succeeded in moving the window.');
        });
        this.sub_windowClass.resize(500, 500, (err: BusinessError) => {
          let errCode: number = err.code;
          if (errCode) {
            console.error(this.TAG, 'Failed to change the window size. Cause:' + JSON.stringify(err));
            return;
          }
          console.info(this.TAG, 'Succeeded in changing the window size.');
        });
        // 3.为子窗口加载对应的目标页面。
        this.sub_windowClass.setUIContent("pages/SubWinLoadPage", (err: BusinessError) => {
          let errCode: number = err.code;
          if (errCode) {
            console.error(this.TAG, 'Failed to load the content. Cause:' + JSON.stringify(err));
            return;
          }
          console.info(this.TAG, 'Succeeded in loading the content.');
          // 3.显示子窗口。
          (this.sub_windowClass as window.Window).showWindow((err: BusinessError) => {
            let errCode: number = err.code;
            if (errCode) {
              console.error(this.TAG, 'Failed to show the window. Cause: ' + JSON.stringify(err));
              return;
            }
            console.info(this.TAG, 'Succeeded in showing the window.');
          });
        });
      })
    }
    console.log(this.TAG, 'showSubWindow end');
  }

  destroySubWindow() {
    // 4.销毁子窗口。当不再需要子窗口时,可根据具体实现逻辑,使用destroy对其进行销毁。
    (this.sub_windowClass as window.Window).destroyWindow((err: BusinessError) => {
      let errCode: number = err.code;
      if (errCode) {
        console.error(this.TAG, 'Failed to destroy the window. Cause: ' + JSON.stringify(err));
        return;
      }
      console.info(this.TAG, 'Succeeded in destroying the window.');
    });
  }

  build() {
    Column() {
      Text("点击创建子窗口")
        .id('SubWinPageHelloWorld')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .onClick(()=>{
          this.showSubWindow();
        })

      Text("点击销毁子窗口")
        .id('SubWinPageHelloWorld')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .onClick(()=>{
          this.destroySubWindow();
        })
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}