【问题标题】:React Native Memory Leakage Animation IssueReact Native 内存泄漏动画问题
【发布时间】:2015-12-20 01:34:33
【问题描述】:

我正在尝试在 React Native 0.17 中构建一个移动台球游戏,以获得经验,并且遇到了有关垃圾收集的问题。现在我有十个同时渲染的圆圈在屏幕上弹跳。但是,应用程序的内存消耗会随着时间的推移而增加,我不知道如何解决这个问题。

这似乎是早期版本中的 React Native 问题,我确实注意到内存随着时间的推移而下降,如图所示,但在更大的应用程序中,我担心这可能是问题。有没有其他人遇到过类似的问题或有解决方案?

相关代码在这里,非常感谢任何帮助。谢谢!

var Test = React.createClass({

getInitialState: function() {
    var circs = [];
    for (var i = 0; i < startCount; i++) {
        circs.push({
            id: i,
            x: 0,
            y: 0,
            vx: 2 + Math.random() * 2,
            vy: 2 + Math.random() * 2,
            dx: 0,
            dy: 0,
            cOb: new Animated.ValueXY({x: 0, y: 0}),
        });
    }

    return {
        circles: circs,
        stop: 1
    };
},
stopCircle: function() {
    this.state.stop = -1 * this.state.stop;
    this.setState(this.state);
},
componentDidMount: function() {
    this.animateCircles();
},
animateCircles: function() {
    this.triggerAnimation(this.animateCircles);
},
triggerAnimation: function(ani) {
    for (var i = 0; i < this.state.circles.length; i++) {
            var cCircle = this.state.circles[i];
            if (cCircle.x * cCircle.x + cCircle.y * cCircle.y > DIST_TO_EDGE * DIST_TO_EDGE) {
                var prevX = cCircle.x - cCircle.vx;
                var prevY = cCircle.y - cCircle.vy;
                var exitX = (1.5 * prevX + .5 * cCircle.x) / 2;
                var exitY = (1.5 * prevY + .5 * cCircle.y) / 2;
                cCircle.x = prevX;
                cCircle.y = prevY;

                var exitRad = Math.sqrt(exitX * exitX + exitY * exitY);
                exitX = exitX * DIST_TO_EDGE / exitRad;
                exitY = exitY * DIST_TO_EDGE / exitRad;

                var twiceProjFactor = 2 * (exitX * cCircle.vx + exitY * cCircle.vy) / (DIST_TO_EDGE * DIST_TO_EDGE);
                cCircle.vx = cCircle.vx - twiceProjFactor * exitX;
                cCircle.vy = cCircle.vy - twiceProjFactor * exitY;
                break;
            }
    }
    if (this.state.stop == 1) {
        for (var k = 0; k < this.state.circles.length; k++) {
            this.state.circles[k].x += this.state.circles[k].vx;
            this.state.circles[k].y += this.state.circles[k].vy;
        }
    }
    this.setState(this.state);
    var animateC = [];
    for (var i = 0; i < this.state.circles.length; i++) {
        var currCirc = this.state.circles[i];
        animateC.push(
            Animated.timing(currCirc.cOb, {
                ...TIMING_CONFIG,
                toValue: {x: currCirc.x, y: currCirc.y}
        }));
    }
    Animated.parallel(
        animateC
    ).start(ani);
},
getStyle: function(which) {
    return [
        styles.circle,
        {transform: this.state.circles[which].cOb.getTranslateTransform()}
    ];
},
render: function() {
    return (
        <View style={styles.container}>
            <View style={styles.edge}>
            </View>
            {
                this.state.circles.map(function(c, i) {
                    return (
                        <TouchableWithoutFeedback key={i} onPress={this.stopCircle}>
                            <Animated.View style={this.getStyle(i)} />
                        </TouchableWithoutFeedback>
                    );
                }, this)
            }
        </View>
    );
}, 

如果您想自己运行应用程序,可以在https://github.com/heliumsoule/React-Native-Pool 找到完整的应用程序。

再次感谢您。

【问题讨论】:

  • this.setState(this.state);那有什么作用?我以前从未遇到过。

标签: android ios animation reactjs react-native


【解决方案1】:

你有很多临时变量,包括简单的数字和对象。我不完全确定这是否会经常被击中,或者动画是否跨越多个帧。如果是每一帧,我猜你只是在执行大量的分配。这些会随着时间的推移而累积,并且在触发垃圾收集器时会导致很少的停顿。

为减少分配次数,您可以将临时变量转换为实例变量,以便重复使用。

我对动画 API 不够熟悉,不知道那里是否有任何优化..

【讨论】:

  • James,我已经尝试了您的建议并创建了实例变量,而不是重新分配变量,但内存使用量仍然会上升(不过会逐渐增加)。
  • 很高兴这有点帮助。请记住,只要您进行分配,您就应该期望内存在被释放之前会缓慢上升。这正是现代 JS VM 的工作方式。可能是时候熟悉调试内存了。应用程序运行后,拍摄几张快照。您可以比较它们以了解使用量的增长情况。
【解决方案2】:

您有两个虚拟机,它们都按照自己的条件执行垃圾收集。 JVM 和 JavaScript。

这篇文章可能会对你有所帮助:

http://moduscreate.com/dynamic-memory-and-v8-with-javascript/

另外,我建议你尽可能多地注释掉代码,看看对内存的影响。然后一点一点地注释一下,看看哪个代码会导致你的内存消耗增长得最快。

【讨论】:

  • 迈克尔,感谢您的文章。我不知道是否有两个虚拟机,因为 JavaScript 是在 React Native 框架中呈现的。我知道主要的内存消耗是每个 TIMING_CONFIG 调用的 triggerAnimation 方法,它只指定调用之间的时间。但是,在 James 的建议之后,我不知道如何进一步优化代码。
  • 我不是android专家,但是React Native框架是Java,用于执行React Native代码的JS引擎是V8。您的应用程序正在从 JavaScript 调用 Java,反之亦然。如果让程序运行很长时间会发生什么? Java 和 V8 都可能会推迟它们的一些垃圾收集,直到设备内存不足或进程使用其限制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-19
  • 2016-08-06
  • 1970-01-01
  • 2016-07-28
相关资源
最近更新 更多