鸿蒙开发5.0【应用异常处理】运维

news2024/9/22 9:35:52

应用异常处理

介绍

本示例介绍了通过应用事件打点hiAppEvent获取上一次应用异常信息的方法,主要分为应用崩溃、应用卡死两种。

效果图预览

1

使用说明

  1. 点击构建应用崩溃事件,3s之后应用退出,然后打开应用进入应用异常页面,隔1min左右后,显示上次异常退出信息。
  2. 点击构建应用卡死事件,需手动退出,然后打开应用进入应用异常页面,隔1min左右后,显示上次异常退出信息。

实现思路

  1. 构建应用异常。源码参考[Index.ets]
/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { hiAppEvent } from '@kit.PerformanceAnalysisKit';
import { PreferencesManager } from '../model/PreferencesManager';
import { BUTTON_TEXT } from '../model/MockData';
import { FaultDataSource } from '../model/DataSource';
import { Logger } from '../log/Logger';


const TAG: string = 'FaultLogger'; // Abnormal Application Page Tag
const DELAY_TIME: number = 3000;

@Entry
@Component
struct ApplicationExceptionView {
  // Initialize the index of the clicked exception event
  @Provide eventIndex: number = -1;

  build() {
    Column() {
      // Scenario description component
      FunctionDescription({
        title: $r('app.string.application_exception_application_fault_title'),
        content: $r('app.string.application_exception_application_fault_description')
      })
      // Abnormal information display component
      FaultArea()
      // Constructing Abnormal Components
      FaultConstruction()
    }
    .padding($r('app.string.ohos_id_card_padding_start'))
    .backgroundColor($r('app.color.ohos_id_color_sub_background'))
    .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
    .height($r('app.string.ohos_global_state_dialog_hundred_percent'))
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])
  }
}

@Component
struct FaultArea {
  // Perform bidirectional data binding on the array length of lazy loading data sources
  @StorageLink('faultDataSourceLength') faultDataSourceLength: number = 0;
  // Bidirectional data binding event group, bound to AppStorage. setOrCreate,
  // this variable changes and triggers the getFaultMessage function
  @StorageLink('appEventGroups') @Watch('getFaultMessage') appEventGroups: Array<hiAppEvent.AppEventGroup> = [];
  // Abnormal trigger sign
  @StorageLink('faultSign') faultSign: boolean = false;
  // The index of the clicked abnormal event
  @Consume eventIndex: number;
  // Data source for lazy loading
  @State faultDataSource: FaultDataSource = new FaultDataSource();
  private scroller: Scroller = new Scroller();

  async aboutToAppear() {
    Logger.info(TAG, `aboutToAppear start`);
    // Get Preferences instance
    await PreferencesManager.getPreferences(this.faultDataSource);
    // First, retrieve data from the persistent storage,
    // then add the previous application exception information to the list header,
    // and update the persistent storage
    this.getFaultMessage();
    // Reset appEventGroups in AppStorage to avoid adding duplicate data
    AppStorage.setOrCreate('appEventGroups', []);
  }

  // Obtain application exception information
  async getFaultMessage() {
    Logger.info(TAG, `getAppEventGroups start`);
    if (this.appEventGroups && this.appEventGroups.length > 0) {
      // Traverse event groups
      this.appEventGroups.forEach((eventGroup: hiAppEvent.AppEventGroup) => {
        // Traverse the collection of event objects
        eventGroup.appEventInfos.forEach(async (eventInfo: hiAppEvent.AppEventInfo) => {
          let message: string = '';
          message += `HiAppEvent eventInfo.domain=${eventInfo.domain}\n`
            + `HiAppEvent eventInfo.name=${eventInfo.name}\n`
            + `HiAppEvent eventInfo.eventType=${eventInfo.eventType}\n`
            + `HiAppEvent eventInfo.params.time=${eventInfo.params['time']}\n`
            + `HiAppEvent eventInfo.params.crash_type=${eventInfo.params['crash_type']}\n`
            + `HiAppEvent eventInfo.params.foreground=${eventInfo.params['foreground']}\n`
            + `HiAppEvent eventInfo.params.bundle_version=${eventInfo.params['bundle_version']}\n`
            + `HiAppEvent eventInfo.params.bundle_name=${eventInfo.params['bundle_name']}\n`
            + `HiAppEvent eventInfo.params.exception=${JSON.stringify(eventInfo.params['exception'])}\n`
            + `HiAppEvent eventInfo.params.hilog.size=${eventInfo.params['hilog'].length}\n`;
          // Knowledge point: Storing exception information in the array faultMessage
          this.faultDataSource.pushData(message);
        })
      })
    }
    // Knowledge point: Persisting storage exception information collection
    this.faultDataSource.persistenceStorage();
  }

  build() {
    List({ scroller:this.scroller }) {
      // Add a judgment, if the number of information in the set of abnormal information is greater than 0, traverse the abnormal information
      if (this.faultDataSourceLength > 0) {
        LazyForEach(this.faultDataSource, (message: string) => {
          ListItem() {
            Text(message)
              .textAlign(TextAlign.Start)
          }
        }, (item: string) => item)
      } else {
        ListItem() {
          // Respond to specified information based on the index of the clicked event
          Text(this.eventIndex === 0 ? $r('app.string.application_exception_crash_event_message') :
            (this.eventIndex === 1 ? $r('app.string.application_exception_freeze_event_message') :
              (this.faultSign ? $r('app.string.application_exception_data_delay_toast') :
              $r('app.string.application_exception_no_message'))))
        }
      }
    }
    .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
    .height($r('app.string.ohos_id_elements_list_high'))
    .borderRadius($r('app.string.ohos_id_corner_radius_default_m'))
    .padding($r('app.string.ohos_id_card_padding_start'))
    .margin({ top: $r('app.string.ohos_id_elements_margin_vertical_l') })
    .backgroundColor(Color.White)
  }
}

@Component
struct FaultConstruction {
  // The index of the clicked abnormal event
  @Consume eventIndex: number;
  // Perform bidirectional data binding on the array length of lazy loading data sources
  @StorageLink('faultDataSourceLength') faultDataSourceLength: number = 0;
  // Abnormal trigger sign
  @StorageLink('faultSign') faultSign: boolean = false;

  handleOperate(index: number) {
    switch (index) {
      case 0:
      // Note: This is a deliberately constructed bug
      // Construct an APP-CRASH scenario in the button click function to trigger an application crash event
        const result: object = JSON.parse('');
        break;
      case 1:
      // Note: This is a deliberately constructed bug
      // Construct an APP-FREEZE scenario in the button click function,
      // trigger the application freeze event, and execute an infinite loop after 500ms
        while (true) {
        }
      default:
        break;
    }
  }

  build() {
    Stack() {
      Column(){
        ForEach(BUTTON_TEXT, (item: string, index: number) => {
          Button(item)
            .type(ButtonType.Capsule)
            .size({ width: $r('app.string.ohos_global_state_dialog_hundred_percent') })
            .borderRadius($r('app.string.ohos_id_corner_radius_default_m'))
            .margin({ top: $r('app.string.ohos_id_button_margin_top') })
            .onClick(() => {
              // Abnormal trigger sign
              this.faultSign = true;
              PreferencesManager.putFaultSign();
              // When clicking on an exception, clear the page information data
              // and display the exception description information.
              // To control the display of page information data,
              // this variable needs to be set to 0
              this.faultDataSourceLength = 0;
              // Update the index of clicked abnormal events
              this.eventIndex = index;
              // Execute system crash operation after 3s
              setTimeout(() => {
                this.handleOperate(index);
              }, DELAY_TIME);
            })
        }, (item: string) => JSON.stringify(item))
      }
      .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
    }
    .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
    .margin({ bottom: $r('app.string.ohos_id_button_margin_bottom')})
    .align(Alignment.Bottom)
    .flexGrow(1)
  }
}

@Component
struct FunctionDescription {
  private title: ResourceStr = '';
  private content: ResourceStr = '';

  build() {
    Column() {
      Row() {
        Text(this.title)
          .fontSize($r('app.string.ohos_id_text_size_headline'))
          .fontWeight(FontWeight.Medium)
          .textOverflow({ overflow: TextOverflow.Ellipsis })
          .maxLines(1)
      }
      .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
      .margin({ bottom: $r('app.string.ohos_id_elements_margin_vertical_m') })
      Row() {
        Text(this.content)
          .wordBreak(WordBreak.NORMAL)
      }
      .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
    }
    .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
    .padding($r('app.string.ohos_id_card_padding_start'))
  }
}
  1. 应用退出后,进入本页面,等待订阅消息通知,待收到订阅消息后,通过EventSubscription.ets中的onReceive函数,接收到异常信息数据,并通过AppStorage.setOrCreate(‘appEventGroups’,异常信息数据)双向绑定异常信息,源码参考代码可参考[EventSubscription.ets]
/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { hiAppEvent } from '@kit.PerformanceAnalysisKit';
import { Logger } from '../log/Logger';

const TAG: string = 'eventSubscription';

export function eventSubscription(): void {
  // Add application event observer method, which can be used to subscribe to application events
  hiAppEvent.addWatcher({
    // Developers can customize observer names, which the system will use to identify different observers
    name: 'mst',
    // Developers can subscribe to system events of interest, where they have subscribed to crash events
    appEventFilters: [
      {
        domain: hiAppEvent.domain.OS,
        names: [hiAppEvent.event.APP_CRASH, hiAppEvent.event.APP_FREEZE]
      }
    ],
    // Knowledge point: Obtain event group information.
    // Developers can implement subscription callback functions themselves,
    // and crash and freeze events will be called back to developers the next time the application starts
    onReceive: async (domain: string, appEventGroups: Array<hiAppEvent.AppEventGroup>) => {
      Logger.info(TAG, `HiAppEvent onReceive: domain=${domain}`);
      // Obtain event group information and perform bidirectional data binding with
      // @StorageLink('faultMessage') faultMessage in the ApplicationException file
      // Performance concerns: If developers have synchronized code that requires time-consuming operations,
      // it is recommended to start worker or taskpool threads to handle it.
      // But if developers use storage and preferences, they can simply call them.
      AppStorage.setOrCreate('appEventGroups', appEventGroups);
    }
  });
}
  1. @StorageLink(‘appEventGroups’)接收订阅事件函数传递的事件组信息,调用getFaultMessage函数对信息进行处理,将处理后的信息通过 this.faultDataSource.pushData(message) 添加到懒加载数据源中,并通过this.faultDataSource.persistenceStorage()执行持久化存储,最后通过使用LazyForEach将数据信息加载到页面上。具体源码参考[Index.ets]
/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { hiAppEvent } from '@kit.PerformanceAnalysisKit';
import { PreferencesManager } from '../model/PreferencesManager';
import { BUTTON_TEXT } from '../model/MockData';
import { FaultDataSource } from '../model/DataSource';
import { Logger } from '../log/Logger';


const TAG: string = 'FaultLogger'; // Abnormal Application Page Tag
const DELAY_TIME: number = 3000;

@Entry
@Component
struct ApplicationExceptionView {
  // Initialize the index of the clicked exception event
  @Provide eventIndex: number = -1;

  build() {
    Column() {
      // Scenario description component
      FunctionDescription({
        title: $r('app.string.application_exception_application_fault_title'),
        content: $r('app.string.application_exception_application_fault_description')
      })
      // Abnormal information display component
      FaultArea()
      // Constructing Abnormal Components
      FaultConstruction()
    }
    .padding($r('app.string.ohos_id_card_padding_start'))
    .backgroundColor($r('app.color.ohos_id_color_sub_background'))
    .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
    .height($r('app.string.ohos_global_state_dialog_hundred_percent'))
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])
  }
}

@Component
struct FaultArea {
  // Perform bidirectional data binding on the array length of lazy loading data sources
  @StorageLink('faultDataSourceLength') faultDataSourceLength: number = 0;
  // Bidirectional data binding event group, bound to AppStorage. setOrCreate,
  // this variable changes and triggers the getFaultMessage function
  @StorageLink('appEventGroups') @Watch('getFaultMessage') appEventGroups: Array<hiAppEvent.AppEventGroup> = [];
  // Abnormal trigger sign
  @StorageLink('faultSign') faultSign: boolean = false;
  // The index of the clicked abnormal event
  @Consume eventIndex: number;
  // Data source for lazy loading
  @State faultDataSource: FaultDataSource = new FaultDataSource();
  private scroller: Scroller = new Scroller();

  async aboutToAppear() {
    Logger.info(TAG, `aboutToAppear start`);
    // Get Preferences instance
    await PreferencesManager.getPreferences(this.faultDataSource);
    // First, retrieve data from the persistent storage,
    // then add the previous application exception information to the list header,
    // and update the persistent storage
    this.getFaultMessage();
    // Reset appEventGroups in AppStorage to avoid adding duplicate data
    AppStorage.setOrCreate('appEventGroups', []);
  }

  // Obtain application exception information
  async getFaultMessage() {
    Logger.info(TAG, `getAppEventGroups start`);
    if (this.appEventGroups && this.appEventGroups.length > 0) {
      // Traverse event groups
      this.appEventGroups.forEach((eventGroup: hiAppEvent.AppEventGroup) => {
        // Traverse the collection of event objects
        eventGroup.appEventInfos.forEach(async (eventInfo: hiAppEvent.AppEventInfo) => {
          let message: string = '';
          message += `HiAppEvent eventInfo.domain=${eventInfo.domain}\n`
            + `HiAppEvent eventInfo.name=${eventInfo.name}\n`
            + `HiAppEvent eventInfo.eventType=${eventInfo.eventType}\n`
            + `HiAppEvent eventInfo.params.time=${eventInfo.params['time']}\n`
            + `HiAppEvent eventInfo.params.crash_type=${eventInfo.params['crash_type']}\n`
            + `HiAppEvent eventInfo.params.foreground=${eventInfo.params['foreground']}\n`
            + `HiAppEvent eventInfo.params.bundle_version=${eventInfo.params['bundle_version']}\n`
            + `HiAppEvent eventInfo.params.bundle_name=${eventInfo.params['bundle_name']}\n`
            + `HiAppEvent eventInfo.params.exception=${JSON.stringify(eventInfo.params['exception'])}\n`
            + `HiAppEvent eventInfo.params.hilog.size=${eventInfo.params['hilog'].length}\n`;
          // Knowledge point: Storing exception information in the array faultMessage
          this.faultDataSource.pushData(message);
        })
      })
    }
    // Knowledge point: Persisting storage exception information collection
    this.faultDataSource.persistenceStorage();
  }

  build() {
    List({ scroller:this.scroller }) {
      // Add a judgment, if the number of information in the set of abnormal information is greater than 0, traverse the abnormal information
      if (this.faultDataSourceLength > 0) {
        LazyForEach(this.faultDataSource, (message: string) => {
          ListItem() {
            Text(message)
              .textAlign(TextAlign.Start)
          }
        }, (item: string) => item)
      } else {
        ListItem() {
          // Respond to specified information based on the index of the clicked event
          Text(this.eventIndex === 0 ? $r('app.string.application_exception_crash_event_message') :
            (this.eventIndex === 1 ? $r('app.string.application_exception_freeze_event_message') :
              (this.faultSign ? $r('app.string.application_exception_data_delay_toast') :
              $r('app.string.application_exception_no_message'))))
        }
      }
    }
    .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
    .height($r('app.string.ohos_id_elements_list_high'))
    .borderRadius($r('app.string.ohos_id_corner_radius_default_m'))
    .padding($r('app.string.ohos_id_card_padding_start'))
    .margin({ top: $r('app.string.ohos_id_elements_margin_vertical_l') })
    .backgroundColor(Color.White)
  }
}

@Component
struct FaultConstruction {
  // The index of the clicked abnormal event
  @Consume eventIndex: number;
  // Perform bidirectional data binding on the array length of lazy loading data sources
  @StorageLink('faultDataSourceLength') faultDataSourceLength: number = 0;
  // Abnormal trigger sign
  @StorageLink('faultSign') faultSign: boolean = false;

  handleOperate(index: number) {
    switch (index) {
      case 0:
      // Note: This is a deliberately constructed bug
      // Construct an APP-CRASH scenario in the button click function to trigger an application crash event
        const result: object = JSON.parse('');
        break;
      case 1:
      // Note: This is a deliberately constructed bug
      // Construct an APP-FREEZE scenario in the button click function,
      // trigger the application freeze event, and execute an infinite loop after 500ms
        while (true) {
        }
      default:
        break;
    }
  }

  build() {
    Stack() {
      Column(){
        ForEach(BUTTON_TEXT, (item: string, index: number) => {
          Button(item)
            .type(ButtonType.Capsule)
            .size({ width: $r('app.string.ohos_global_state_dialog_hundred_percent') })
            .borderRadius($r('app.string.ohos_id_corner_radius_default_m'))
            .margin({ top: $r('app.string.ohos_id_button_margin_top') })
            .onClick(() => {
              // Abnormal trigger sign
              this.faultSign = true;
              PreferencesManager.putFaultSign();
              // When clicking on an exception, clear the page information data
              // and display the exception description information.
              // To control the display of page information data,
              // this variable needs to be set to 0
              this.faultDataSourceLength = 0;
              // Update the index of clicked abnormal events
              this.eventIndex = index;
              // Execute system crash operation after 3s
              setTimeout(() => {
                this.handleOperate(index);
              }, DELAY_TIME);
            })
        }, (item: string) => JSON.stringify(item))
      }
      .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
    }
    .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
    .margin({ bottom: $r('app.string.ohos_id_button_margin_bottom')})
    .align(Alignment.Bottom)
    .flexGrow(1)
  }
}

@Component
struct FunctionDescription {
  private title: ResourceStr = '';
  private content: ResourceStr = '';

  build() {
    Column() {
      Row() {
        Text(this.title)
          .fontSize($r('app.string.ohos_id_text_size_headline'))
          .fontWeight(FontWeight.Medium)
          .textOverflow({ overflow: TextOverflow.Ellipsis })
          .maxLines(1)
      }
      .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
      .margin({ bottom: $r('app.string.ohos_id_elements_margin_vertical_m') })
      Row() {
        Text(this.content)
          .wordBreak(WordBreak.NORMAL)
      }
      .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
    }
    .width($r('app.string.ohos_global_state_dialog_hundred_percent'))
    .padding($r('app.string.ohos_id_card_padding_start'))
  }
}
  1. 以上代码中有引用懒加载数据类和持久化存储类,源码可参考[DataSource.ets]
/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { PreferencesManager } from './PreferencesManager';

// Basic implementation of IDataSource to handle data listener
class BasicDataSource implements IDataSource {
  // Data change listener
  private listeners: DataChangeListener[] = [];
  // Data sources that require data iteration
  private originDataArray: string[] = [];

  // Obtain the length of data
  public totalCount(): number {
    return 0;
  }

  // Get specified data items
  public getData(index: number): string {
    return this.originDataArray[index];
  }

  // This method is called on the framework side to add a listener listener
  // to the LazyForEach component's data source for listening
  registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      console.info('add listener');
      this.listeners.push(listener);
    }
  }

  // This method is called on the framework side to remove listener listening
  // at the data source for the corresponding LazyForEach component
  unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener);
    if (pos >= 0) {
      console.info('remove listener');
      this.listeners.splice(pos, 1);
    }
  }

  // Notify LazyForEach component to overload all child components
  notifyDataReload(): void {
    this.listeners.forEach(listener => {
      listener.onDataReloaded();
    })
  }

  // Notify LazyForEach component to add sub components at
  // the index corresponding to the index
  notifyDataAdd(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataAdd(index);
    })
  }

  // Notify the LazyForEach component that there is a change in data at
  // the index corresponding to the index, and that the subcomponent needs to be rebuilt
  notifyDataChange(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataChange(index);
    })
  }

  // Notify LazyForEach component to delete the subcomponent at the index corresponding to the index
  notifyDataDelete(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataDelete(index);
    })
  }
}

export class FaultDataSource extends BasicDataSource {
  // Lazy loading data
  private faultMessage: Array<string> = [];

  // Knowledge point: Obtaining the data length of lazy loading data sources
  totalCount(): number {
    return this.faultMessage.length;
  }

  // Get specified data items
  getData(index: number): string {
    return this.faultMessage[index];
  }

  // Knowledge point: Storing data into lazy loading data sources
  pushData(data: string): void {
    this.faultMessage.unshift(data);
    // Add data to the array header
    this.notifyDataAdd(0);
    AppStorage.setOrCreate('faultDataSourceLength', this.totalCount());
  }

  // Knowledge point: Persisting storage exception information collection
  persistenceStorage(): void {
    PreferencesManager.putFaultMessage(this.faultMessage);
  }
}

和参考源码:[PreferencesManager.ets]

/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { preferences as dataPreferences } from '@kit.ArkData';
import { BusinessError } from '@kit.BasicServicesKit';
import { FaultDataSource } from '../model/DataSource';
import { Logger } from '../log/Logger';

// Knowledge point: Initialize Preferences instances for persistent storage of
//  exception information and the ability to retrieve persistent data
let dataPreferencesManager: dataPreferences.Preferences = {} as dataPreferences.Preferences;

export class PreferencesManager {
  // Get Preferences instance
  public static async getPreferences(faultDataSource: FaultDataSource): Promise<void> {
    Logger.info('getPreferences start.');
    try {
      let val: dataPreferences.Preferences = await (dataPreferences.getPreferences(AppStorage.get('context'),
        'myStore') as Promise<dataPreferences.Preferences>);
      dataPreferencesManager = val;
      Logger.info('Succeeded in getting preferences.');
      // Get abnormal information
      await PreferencesManager.getFaultMessage(faultDataSource);
      await PreferencesManager.getFaultSign();
    } catch (err) {
      Logger.error('Failed to get preferences');
    }
  }

  /**
   * Storing abnormal data information
   * @Param faultMessage exception information set
   */
  public static async putFaultMessage(faultMessage: Array<string>): Promise<void> {
    Logger.info(`putMessage start`);
    try {
      // Knowledge point: Storing data through the dataPreferencesManager.put method
      dataPreferencesManager.put('faultMessage', JSON.stringify(faultMessage), async (err: BusinessError) => {
        if (err) {
          Logger.error(`Failed to put value of 'faultMessage'. code =` + err.code + ', message =' + err.message);
          return;
        }
        Logger.info('Succeeded in putting value of faultMessage.');
        dataPreferencesManager.flush();
      })
    } catch (err) {
      Logger.error(`Failed to put value of 'catch err'. code =` + err.code + ', message =' + err.message);
    }
  }

  /**
   * Get abnormal data information
   * @Param faultMessage exception information set
   */
  public static async getFaultMessage(faultDataSource: FaultDataSource): Promise<void> {
    Logger.info(`getFaultMessage start`);
    try {
      // Knowledge point: Obtaining abnormal information data through the dataPreferencesManager.get method
      const data: dataPreferences.ValueType = await dataPreferencesManager.get('faultMessage', []);
      if (typeof data === 'string') {
        const faultData: Array<string> = JSON.parse(data);
        // Add abnormal data to lazy loading data source
        faultData.forEach((item: string) => {
          faultDataSource.pushData(item);
        })
        // Bidirectional data binding lazy loading data source length, updating data source length
        AppStorage.setOrCreate('faultDataSourceLength', faultDataSource.totalCount());
        Logger.info('Succeeded in getting value of faultMessage.');
      }
    } catch (err) {
      Logger.error(`Failed to get value of 'catch err'. code =` + err.code + ', message =' + err.message);
    }
  }

  /**
   * Storage data sign
   */
  public static async putFaultSign(): Promise<void> {
    Logger.info(`putMessage start`);
    try {
      // Knowledge point: Storing data through the dataPreferencesManager.put method
      dataPreferencesManager.put('faultSign', JSON.stringify(true), async (err: BusinessError) => {
        if (err) {
          Logger.error(`Failed to put value of 'faultSign'. code =` + err.code + ', message =' + err.message);
          return;
        }
        Logger.info('Succeeded in putting value of faultSign.');
        dataPreferencesManager.flush();
      })
    } catch (err) {
      Logger.error(`putFaultSign Failed to put value of 'catch err'. code =` + err.code + ', message =' + err.message);
    }
  }

  /**
   * Get abnormal data information
   */
  public static async getFaultSign(): Promise<void> {
    Logger.info(`getFaultMessage start`);
    let faultSign: boolean = false;
    try {
      // Knowledge point: Obtain exception identifiers through the dataPreferencesManager.get method
      const data: dataPreferences.ValueType = await dataPreferencesManager.get('faultSign', faultSign);
      if (typeof data === 'string') {
        faultSign = JSON.parse(data);
        AppStorage.setOrCreate('faultSign', faultSign);
      }
    } catch (err) {
      Logger.error(`getFaultSign Failed to get value of 'catch err'. code =` + err.code + ', message =' + err.message);
    }
  }
}

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
1

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

在这里插入图片描述

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1995044.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java学习笔记(二十):反射、动态代理、日志、类加载器、xml、单元测试Junit、注解

目录 一、反射 1.1 反射的概述&#xff1a; 1.2 学习反射到底学什么&#xff1f; 1.3 获取字节码文件对象的三种方式 1.4 字节码文件和字节码文件对象 1.5 获取构造方法 1.6 获取构造方法并创建对象 1.7 获取成员变量 1.8 获取成员变量并获取值和修改值 1.9 获取成员…

002集——C#基本语法——C#学习笔记

C# 是一种面向对象的编程语言。在面向对象的程序设计方法中&#xff0c;程序由各种相互交互的对象组成。相同种类的对象通常具有相同的类型&#xff0c;或者说&#xff0c;是在相同的 class 中。 例如&#xff0c;以 Rectangle&#xff08;矩形&#xff09;对象为例。它具有 le…

一文读懂如何选择视频孪生三维建模方式及建模精度等级

导言/INTRODUCTION 三维模型是视频孪生应用的基础&#xff0c;建模方式与模型精度将直接影响到最终孪生场景的呈现和应用效果。各种建模方式和模型精度在成本、场景还原真实度、实施周期方面都有自己的特点&#xff0c;因而有着各自的优劣势和适用场景&#xff0c;同一场景可能…

基于Hadoop的国内手机销售大数据分析与可视化研究【百万数据集】

文章目录 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目介绍 绪论研究背景研究目的研究意义 相关技术理论介绍Hadoop相关理论HIve数据仓库flume组件介绍sqoop组件介绍Pyecharts介绍 数据来源及处理数据介绍数据预处理 Hadoop集群搭建Hadoop全…

安装python+python的基础语法

安装python python2为内置&#xff0c;安装python3----3.6.8 最新安装3.12使用源码安装 1.查看yum源&#xff0c;epel [rootpython01 ~]# yum list installed |grep epel 2.安装python3 [rootpython01 ~]# yum -y install python3 3.查看版本 [rootpython01 ~]# python…

计算机硬件 课程导读

目录 一、老师介绍 二、课程目标 三、课程大纲 一、老师介绍 学问小小谢 我是一个热爱分享知识的人&#xff0c;我深信知识的力量能够启迪思考&#xff0c;丰富生活。 欢迎每一位对知识有渴望的朋友&#xff0c;如果你对我的创作感兴趣&#xff0c;或者我们有着共同的兴趣点&…

vue3组件之间通讯

1. props&#xff0c;实现父组件向子组件通讯。 父组件 &#xff1a;对子组件属性绑定要通讯的数据。 子组件&#xff1a;通过defineProps来进行数据接收。 2. emit&#xff0c;实现子组件向父组件通讯。 子组件&#xff1a;通过emit创建向父组件传递数据事件 父组件&#…

Chromium编译指南2024 - Android篇:环境准备(二)

1.引言 在前面的章节中&#xff0c;我们详细介绍了编译 Chromium for Android 所需的系统和硬件要求。在确保您的开发环境符合这些基本要求后&#xff0c;接下来我们将重点讲解如何具体配置您的开发环境&#xff0c;以便顺利编译 Chromium。本篇文章将涵盖从更改软件源到安装基…

[matlab] 鲸鱼优化算法优化KNN分类器的特征选择

目录 引言 智能优化算法概述 智能优化算法在KNN特征选择中的应用 应用步骤 UCI数据集 鲸鱼优化算法 一、算法背景与原理 二、算法组成与步骤 三、算法特点与优势 四、应用与挑战 代码实现 鲸鱼优化算法 主程序 打印结果 引言 智能优化算法在优化KNN&#xff08;…

5、关于kali搭建vulhub

Vulhub是一个基于Docker和Docker-compose的漏洞靶场环境&#xff0c;所以搭建vulhub分三步&#xff1a; 1、安装docker 2、安装docker-compose 3、安装vulhub 一、安装步骤 1、安装docker 因为kali太久没用&#xff0c;所以需要先更新软件列表最新源 apt-get update 安装do…

C++ vector的基本使用

目录 1. vector的定义 2. 迭代器iterator的使用 3. vector空间增长问题 (1). size与capacity (2). empty与resize与reserve 4. vector的增删查改 (1) . push_back和pop_back (2). find与insert与erase (3). swap与operator[] 5. vector迭代器失效问题 (1). 改变空间 (…

爱玛电动车今年多次抽查不合格:营收增速放缓承压,拟50亿扩产能

《港湾商业观察》廖紫雯 7月26日&#xff0c;市场监管总局发布《2024年上半年电动自行车产品质量国家监督专项抽查结果情况通报》&#xff0c;爱玛电动车五次上榜。 除却一直以来被多次诟病的电动车产品质量问题外&#xff0c;业绩层面上&#xff0c;近两年数据来看&#xff…

从格斗项目的着装和格斗术,理解巴黎奥运会上的拳击、跆拳道、柔道、摔跤之间到底有什么区别?

文章目录 引言I 柔道着装格斗术II 摔跤装备“摔跤耳”格斗术:古典式摔跤和自由式摔跤III 跆拳道装备格斗术等级段位制(“十级九段制”)IV 拳击装备格斗术拳击手小结引言 8月1日巴黎,柔道女子-78公斤级比赛结束,意大利贝兰迪夺得金牌,以色列拉尼尔摘得银牌,中国选手马振昭和…

SAM-Med2D 大模型学习笔记(续):训练自己数据集

1、前言、数据集介绍 SAM-Med2D大模型介绍参考上文&#xff1a;第三章&#xff1a;SAM-Med2D大模型复现-CSDN博客 本文将使用SAM-Med2D大模型训练自己的数据集 关于SAM-Med2D大模型官方demo数据集的介绍上文已经介绍过&#xff0c;这里简单回顾下 其中data_demo为数据集的目…

你的工作环境,选对劳保鞋了吗?守护安全,从脚下开始!

在众多的工作场所中&#xff0c;我们穿梭于不同的工作环境&#xff0c;从繁忙的工厂车间到复杂的建筑工地&#xff0c;再到需要精细操作的实验室……每一步都承载着对安全的期许和对效率的追求。但你是否意识到&#xff0c;脚下那双不起眼的劳保鞋&#xff0c;其实是守护你安全…

洞见优维「全面可观测」:从85%的AI项目败率说起

一直以来&#xff0c;优维都坚信AI有潜力改变运维行业并促进创新&#xff0c;这是我们的A面。但从行业和客户那里&#xff0c;我们所看到的B面也不容忽视。 自从去年底发布优维全面可观测以来&#xff08;点击回顾&#xff09;&#xff0c;我们的团队在服务客户的进程中常常感…

国内下载gradle慢,下载gradle超时问题解决【笔记】

下载gradle超时、慢 修改 找到项目中的gradle-wrapper.properties文件 修改 替换默认下载链接地址 distributionUrlhttps\://services.gradle.org/distributions替换为腾讯或阿里的链接地址 厂商链接阿里https://mirrors.aliyun.com/macports/distfiles/gradle腾讯https://…

vue请求springboot接口下载zip文件

说明 其实只需要按照普通文件流下载即可&#xff0c;以下是一个例子&#xff0c;仅供参考。 springboot接口 RestController RequestMapping("/api/files") public class FileController {GetMapping("/download")public ResponseEntity<Resource>…

C++ 多态三

1.多态的概念 多态的前提的是继承。当不同的对象去完成同一种行为时会产生不同的结果就是多态的通俗意义。 例如学生、成人两个对象去完成买票这个行为&#xff0c;那么学生的结果是获得半价&#xff0c;而成人获得的结果的是全价。 2.多态的定义及实现 2.1构成多态的两个硬…

自闭症学校排名前十,揭秘顶级干预学校

在当今社会&#xff0c;自闭症儿童的数量不断上升&#xff0c;众多家庭都在全力以赴地为孩子寻找适宜的自闭症学校。当面临这一重要抉择时&#xff0c;家长们常常首先想到的便是查看自闭症学校排名前十的榜单。然而&#xff0c;网络上此类排名繁多&#xff0c;其真实性与可靠性…