在离子内存泄漏(或角)? [英] Memory leak in Ionic(or angular)?

查看:124
本文介绍了在离子内存泄漏(或角)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新来的这两种离子和角度,所以我不知道哪里出了问题实际上在于两者之间(如果任一)。我似乎有NG-重复不清除内存出现问题。我写了一个光秃秃的骨头例子来演示

I'm new to both Ionic and Angular, so I'm not sure where the problem would actually lie between the two(if either). I seem to have a problem with ng-repeat not clearing memory. I've written a bare bones example to demonstrate

HTTP://$c$cpen.io/pen/pvQyxj

index.html的

index.html

<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title></title>

    <link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet">

    <!-- ionic/angularjs js -->
    <script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
    <script src="cordova.js"></script>
    <script src="js/app.js"></script>

  </head>
  <body ng-app="starter">

    <ion-pane>
      <ion-header-bar class="bar-stable">
        <h1 class="title">Ionic Blank Starter</h1>
      </ion-header-bar>
      <ion-content ng-controller="CardsCtrl">
    <div ng-repeat="card in cards" on-tap="start(1000)">
        <img ng-src="{{card.image}}">
    </div>
      </ion-content>
    </ion-pane>
  </body>
</html>

JS / app.js

js/app.js

angular.module('starter', ['ionic'])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });

}).controller('CardsCtrl', function($scope) {
    $scope.cards = [];


    var addCards = function(_num, y) {
        for (var x = 0; x < _num; x++) 
        {
            $scope.cards.push({
                image:"http://i.imgur.com/QR8mZAt.jpg?"+y
            }); 
        }
    }
    addCards(1, "new");

    var cardDestroyed = function(y) {

        //console.log("destroy");
        $scope.cards.splice(0, 1);
        addCards(1, y);
    };

    $scope.start = function(y){
        console.log("start");
        for (var x = 0; x < y; x++)
        {
            cardDestroyed(y);
        }
        console.log("stop");
    }
})

每次点击图片,阵列NG重复使用将有一个元素删除,并添加1000倍。但有一点粘在内存中,引起我的实际应用程序崩溃。

every time you click the picture, the array ng-repeat is using will have an element removed and added 1000 times. But there is something sticking around in memory, causing my actual app to crash.

任何人都可以摆脱一些有识之士来,如果我做错了什么,或者如果它实际上是一个错误?我已经通过github上看起来并没有看到它匹配我所看到的一个bug报告,有一次我已经确定了它不只是我做错了,我会去作报告。

Can anyone shed some insight as to if I'm doing something wrong, or if it's actually a bug? I've looked through github and haven't seen a bug report which matches what I'm seeing, and once I've determined it's not just me doing something wrong I'll go make a report.

推荐答案

如果您按照图表,你可以看到,问题是发出事件侦听器的数量。由于方式, $观看工作中的角,从数组中移除元素,然后添加一个新的元素不会删除 $看旧的元素,引起事件侦听器的数量继续无限产卵。

If you follow the chart, you can see that the issue is the number of Event Listeners that are issued. Due to the way that $watch works within angular, removing an element from an array and then adding a new element doesn't remove the $watch on the old element, causing the number of Event listeners to continue to spawn infinitely.

默认情况下, $腕表()的唯一功能检查对象引用相等。这意味着,在每个 $摘要,角将检查是否新老值是相同的物理对象。这意味着,香草 $表()语句只会调用它的处理程序,如果你确实改变基本对象的引用。

By default, the $watch() function only checks object reference equality. This means that within each $digest, angular will check to see if the new and old values are the same "physical" object. This means that the vanilla $watch() statement will only invoke its handler if you actually change the underlying object reference.

有两种方法来解决这个问题。首先,你可以使用语法一旦新的绑定是在角1.3提供。更改 NG-重复 NG-重复=卡牌::将创建一个绑定只有等到前pression进行评估,然后销毁监听器。在这里你知道,一旦它被评估的元素永远不会改变,这是最理想的情况。

There are two ways to solve this issue. Firstly, you can use the new Bind Once syntax that is provided in Angular 1.3. Changing your ng-repeat to ng-repeat="card in ::cards" will create a bind only until the expression is evaluated, then destroy the listener. This is ideal for situations where you know that the element will never change once it's been evaluated.

另一种方法是使用一个更积极跟踪上的元素。 NG-重复=卡牌轨道由$ id为将导致元素由 $ ID来跟踪场,和角就能巧妙除去听者时具有独特的 $的对象id 不再在DOM中存在

The other method is to use a more aggressive tracking on the elements. ng-repeat="card in cards track by $id" will cause the elements to be tracked by the $id field, and angular will be able to smartly remove the listener when the object with the unique $id no longer exists in the DOM.

在时间轴看着这两个,你会看到,第一个选项绑定一旦将花费更多的时间,没有听众,因为它会评估后破坏听众,只产生新的听众新的元素添加到DOM。第二个选项将花大部分是在为听众您的积极元素数量的上限时间,但会掉落所有的听众作为元素被删除,并添加新的听众,以取代他们。

Watching both of these in the timeline, you will see that the first option Bind Once will spend more time with no listeners, as it will destroy the listeners after evaluation and only spawn new listeners to add the new elements to the DOM. The second option will spend most of it's time at the upper bounds of listeners for your number of active elements, but will drop all the listeners as elements are removed and add new listeners to replace them.

在最后,一旦绑定效率会更高,如果你知道的元素都不会改变,只是更换;跟踪将更加灵活,如果被添加和删除您的元素之间会发生变化。

In the end, Bind Once will be more efficient if you know the elements aren't going to change, only be replaced; Tracking will be more flexible if your elements could change between being added and removed.

这篇关于在离子内存泄漏(或角)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆