离子性4.2.1模态内存泄漏

时间:2018-11-06 18:39:30

标签: ios angular ionic-framework memory-leaks modal-dialog

我一直在使用Ionic开发一个信息亭应用程序,以在12.9英寸iPad Pro上使用。随着这些应用程序的运行,运行了几周,我注意到动画性能(尤其是带有<ion-slides>元素)的性能下降并被追踪它回到内存泄漏中。我在此应用中使用了两种模式,当其中一种模式都被关闭时,如果我强制进行垃圾回收,则可以在Chrome开发人员工具中查看内存分配时间轴和内存快照,我可以看到那里的模式作为分离的DOM元素。每次关闭并重新打开模式时,分配的内存都会稍大一点。其中一个模式非常复杂,带有动态src <video>元素和关联的播放控制按钮,但另一个非常简单,仅包含使用* ngFor从json数据中提取的一些文本元素。

通常,此内存泄漏不足以担心。典型的用户永远不会在合理的时间范围内打开和关闭模态足以引起问题。但是,这些iPad在公共场所,每天只有成百上千的用户使用此应用。根据我们的忙碌程度,大约需要一周的时间才能使用内存泄漏引起的明显问题。他们正在单应用程序模式下运行它。因此,要重新启动它们,我必须解锁信息亭外壳,取回iPad,将它们连接到计算机上的Configurator,重新启动它们,然后将它们重新安装在外壳中。如果可以避免的话,这并不是我每几天要做的事情。

我在GitHub和GitHub上也找到了其他类似问题的帖子,但没有任何真实答案。有什么方法可以确保这些模态在被解散时被正确地销毁?

离子不是我典型的开发平台。我通常在React中工作,但有人决定我们必须为此使用iPad,尽管我们所有人都告诉他们这是一个糟糕的主意。因此,我完全有可能是个白痴,显然我在这里很想念。

谢谢!

更简单的代码是...

JS

import { Component } from '@angular/core';
import { NavController, NavParams, Events, ViewController } from 'ionic-angular';
import { CreditsProvider } from '../../providers/credits/credits';

/**
 * Generated class for the CreditsModalPage page.
 *
 * See https://ionicframework.com/docs/components/#navigation for more info on
 * Ionic pages and navigation.
 */

@Component({
  selector: 'page-credits-modal',
  templateUrl: 'credits-modal.html',
})
export class CreditsModalPage {
  public games = [];
  public ahStaff = [];
  public playCapture = [];

  constructor(private creditsProvider: CreditsProvider, public navCtrl: NavController, public navParams: NavParams, public events: Events, private viewCtrl: ViewController) {
    events.subscribe('timeout', (state) => {
      if (state === 'home') {
        this.viewCtrl.dismiss();
      }
    })
  }

  ionViewDidLoad() {
    this.creditsProvider.getCredits().subscribe((response) => {
      this.games = response.games;
      this.ahStaff = response.ahStaff;
      this.playCapture = response.playCapture;

      //update all staff to not show easter egg
      this.ahStaff.forEach(staff => {
        staff.showNickname = false;
      });
    });
  }

  /*
  * If the staff member has a nickname, toggle the easter egg on and off
  */
  toggleEasterEgg(index) {
    if(this.ahStaff[index].nickname !== null){//if they have a nickname
      //toggle the easter egg
      this.ahStaff[index].showNickname = !this.ahStaff[index].showNickname;
    }
  }
}

HTML

<!--
  Generated template for the CreditsModalPage page.

  See http://ionicframework.com/docs/components/#navigation for more info on
  Ionic pages and navigation.
-->
<ion-header>

  <ion-navbar color="dark">
    <ion-title>Credits</ion-title>
  </ion-navbar>

</ion-header>


<ion-content padding class="creditsContent">
  <h1>Staff</h1>
  <div class="credit" *ngFor="let staff of ahStaff; let i = index">
    <p (click)="toggleEasterEgg(i)" >{{staff.role + ' - '}}<span [ngClass]="{'glitch': staff.showNickname}" [attr.data-text]="staff.nickname">{{staff.showNickname ? staff.nickname : staff.name}}</span></p>
  </div>
  <h1>Play Capture</h1>
  <div class="credit" *ngFor="let player of playCapture">
    <p>{{player}}</p>
  </div>
  <h1>Games</h1>
  <div class="credit" *ngFor="let game of games">
    <h2>{{game.name}}</h2>
    <p *ngIf="game.year !== null">{{"Year Published - " + game.year}}</p>
    <p *ngIf="game.developer !== null">{{"Developer - " + game.developer}}</p>
    <p *ngIf="game.publisher !== null">{{"Publisher - " + game.publisher}}</p>
    <p *ngIf="game.note !== null">{{game.note}}</p>
  </div>

</ion-content>

2 个答案:

答案 0 :(得分:0)

您需要取消订阅所有永远不会完成的订阅。

private onTimeout = (state) => {
    if (state === 'home') {
      this.viewCtrl.dismiss();
    };
}

ionViewDidLoad() {
    this.events.subscribe('timeout', onTimeout);
}

ionViewWillLeave() {
    this.events.unsubscribe('timeout', onTimeout);
}

答案 1 :(得分:0)

感谢您的帮助@Gilsdav。但是,这似乎是离子本身的问题。我做了起初应该做的事情,直接去了Ionic Modal文档here,并使用那里的示例查找内存泄漏。果然,我看到的是完全相同的行为。 Ionic Docs Performance Timeline。侦听器,JS堆和文档都在垃圾回收上得到了清理,但是DOM节点不断攀升。查看堆快照,我将模态的全部内容视为分离的DOM元素,就像我对自己的代码所做的一样。

在99 %%以上的用例中,此泄漏足够小,不会成为大问题。因此,我不会将Ionic视为一个大问题。但是,我必须能够一次连续运行几个月,而不会出现问题。因此,看来我将寻找一种重新格式化此方式以不使用模式的方法,或者不得不寻找一种每晚重新启动iPad的方法。

更新!

因此,如果有人需要解决此问题的方法,这就是我最终要做的。我不确定这是否正确,但似乎可行。

问题模态之一是超时提示,它只是定期确保有人还在。如果没有人响应,只需将应用重置为主视图。取消此模式后,我只是调用了window.location.reload()重新加载了该应用程序。在Chrome中进行测试时,它看起来绝对不漂亮,但在设备上运行时,实际上却是无缝的。

通过Safari开发人员工具查看实际设备上的javascript分配,我可以看到实时尺寸随着我打开和关闭模态而稳定增加。但是,一旦该超时模态消失并重新加载,它将立即回到原始级别。

相关问题