0

我正在尝试完成折线收缩的简单动画。我正在访问加速度计 X 值,将其添加到点数组/列表中,然后更新所有这些点的 x 坐标。这是一张图:

在此处输入图像描述

例如,假设我的 SCREEN_WIDTH 是 800 像素。

第 1 步:我添加新点 A = (0, 9.43634),没有绘制任何内容,因为我至少需要 2 个点

points[(0, 9.43634)];

第 2 步:我添加另一个点 B = (0, 7.23134)。我重新计算新的 X 值,然后使用这些点绘制折线:

points[(0, 9.43634), (800, 7.23134)];

第 3 步:我添加另一个点 C = (0, 8.251251)。我重新计算 X 值,然后使用这些点绘制折线:

points[(0, 9.43634), (400, 7.23134), (800, 8.251251)];

第 4 步: ...

我的问题是动画不流畅。当我将要添加的最大点数设置为 ~100 时,它似乎会跳过帧。看起来动画在添加单个点后没有刷新,而是在添加了几个点后刷新。

我尝试使用数组而不是 ArrayList 来避免垃圾收集,我尝试限制动画速度等,但没有任何效果。

计算新的 x 值并使用 100 多个点绘制折线会很慢吗?我也尝试在相邻点之间画线,但性能是一样的。

如果它很重要,我正在三星 Galaxy S2 上进行测试。

太糟糕了,我不能在这里发布它的动画,但这里是所有必要的代码:

Accelerometer_Test.java 来自 accelerometer-test 项目:

我把它贴在这里是因为我认为它太长了

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gurniak.accelerometer.test"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk android:minSdkVersion="5" android:targetSdkVersion="18" />

<uses-permission android:name="android.permission.WAKE_LOCK"/>

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:allowBackup="true" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:screenOrientation="landscape"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

来自 accelerometer-test-android 项目的 MainActivity.java:

package com.gurniak.accelerometer.test;

import android.os.Bundle;

import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import android.util.Log;

public class MainActivity extends AndroidApplication {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
        cfg.useGL20 = true;
        cfg.useAccelerometer = true;
        cfg.useCompass = false;
        cfg.useWakelock = true;

        initialize(new Accelerometer_Test(), cfg);
    }
}

我的问题是:如何加快动画速度并使其更加流畅?我希望它快速更新(每个 ~20[ms] 将是完美的),并且在添加到pointsX. 我在这里做一些非常愚蠢的事情吗?GC_CONCURRENT FREED即使在达到MAX_NUM_POINTS限制后没有添加新点,我也会在我的 logcat 中反复看到。最后,如果重新计算新的 x 值实际上对性能不利,是否有任何算法可以更快地重新计算它?

4

3 回答 3

1

我解决了我的问题。我做错了三件事:

1)我在画,然后更新,这是我应该做的相反的顺序。

2)我在render()方法中分配新对象,使垃圾收集器发疯:

points.add(new Vector2(0, newValue));

3)我使用整数步而不是浮点步,这就是动画不流畅的原因:

int step = (int) Math.ceil(SCREEN_WIDTH / ((points.size - 1) * 1.0));
于 2013-09-29T15:55:24.813 回答
1

使用分析器或检测您的代码以查看时间的去向。Android DDMS 工具非常适合跟踪分配。

渲染中的打嗝通常是由垃圾收集引起的,是由在渲染循环中分配“太多”(即大多数东西)引起的,所以这就是我要开始的地方。但是在尝试优化代码时,您应该找到并遵循实际的硬数据。Vector2如果它与分配相关,请尝试将所有“点”对象预分配到create.

于 2013-09-23T12:36:00.497 回答
0

尝试使用至少两个或三个线程的线程池,这样您就不会占用您的 UI 线程并且可以将工作卸载到其他内核。然后可以使用 UI 线程上的Ahandler接收具有 X、Y 和时间戳的消息,以便 UI 可以保持最新。

ThreadPool类示例所示的设置可以很好地解决这个问题。除了线程池,它还展示了如何重用相同的变量来防止不必要的内存分配和垃圾收集。这些可能是昂贵的操作,每次 GC 运行时,在您的应用程序甚至有机会开始更新之前,它本身将花费 +20 毫秒。

为多个线程创建管理器

Google I/O 上也有很多关于优化应用程序的讨论,值得一试。

Google I/O 2009 - 为 Android 编写实时游戏 Google I/O 2011 - 加速 Android 渲染

于 2013-09-23T08:56:21.697 回答