Celebes
Celebes

Reputation: 1431

Animation is choppy and isn't updated as often as it should

I am trying to complete simple animation of polyline shrinking. I am accessing accelerometer X value, adding it to an array/list of points, and then updating the x coordinate of all those points. Here's a drawing:

enter image description here

so let's say for example that my SCREEN_WIDTH is 800 px.

step 1: I add new point A = (0, 9.43634), nothing is drawn because I need at least 2 points

points[(0, 9.43634)];

step 2: I add another point B = (0, 7.23134). I recalculate new X values, then I draw polyline using those points:

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

step 3: I add yet another point C = (0, 8.251251). I recalculate X values, then I draw polyline using those points:

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

step 4: ...

My problem is that animation isn't fluid. When I set max number of points to be added to ~100 it seems to skip frames. It looks like if animation wasn't refreshed after adding a single points but rather after adding a couple of them.

I've tried using arrays instead of ArrayList to avoid garbage collection, I've tried limiting animation speed etc. but nothing works.

Is calculating new x values and drawing a polyline using 100+ points that slow? I also tried drawing lines between adjacent points but performance was the same.

I am testing on Samsung Galaxy S2 if it's important.

Too bad I can't post an animation of what it looks like here, but here is all necesarry code:

Accelerometer_Test.java from accelerometer-test project:

I've pasted it here because it is too long in my opinion

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>

MainActivity.java from accelerometer-test-android project:

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);
    }
}

My question is: how can I speed the animation up and make it more fluid? I want it to update fast (each ~20[ms] would be perfect) and after every point added to pointsX. Am I doing something extremely stupid here? I see in my logcat GC_CONCURRENT FREED repeatedly even though new points aren't being added after reaching MAX_NUM_POINTS limit. Finally, if recalculating new x values is in fact that bad for performance are there any algorithms to recalculate it faster?

Upvotes: 0

Views: 405

Answers (3)

Celebes
Celebes

Reputation: 1431

I solved my problem. There were three things that I did wrong:

1) I was drawing, then updating, which is a reversed order of what I should do.

2) I was allocating new objects inside render() method drawing Garbage Collector crazy:

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

3) I was using integer step instead of float step and that's why animation wasn't fluid:

int step = (int) Math.ceil(SCREEN_WIDTH / ((points.size - 1) * 1.0));

Upvotes: 1

P.T.
P.T.

Reputation: 25177

Use a profiler or instrument your code to see where the time is going. The Android DDMS tools are pretty good for tracking allocations down.

Hiccups in rendering are often caused by garbage collections, caused by allocating "too much" (i.e., most anything) in the render loop, so that's where I would start. But you should find and follow actual hard data when trying to optimize your code. If it is allocation related, try pre-allocating all your "point" Vector2 objects in create.

Upvotes: 1

Jon
Jon

Reputation: 1388

Try using a thread pool of at least two or three threads, that way you're not tying up your UI thread and work can be offloaded to other cores. A handler on the UI thread can then be used to receive messages that have the X, Y and a timestamp so that the UI can be kept up to date.

A setup like the ThreadPool class example shows would work well for this. Along with the thread pool it also shows how you can reuse the same variables to prevent the unnecessary memory allocations and garbage collection. Those can be expensive operations and every time the GC runs it's going to take +20ms itself before your app even gets a chance to start updating.

Creating a Manager for Multiple Threads

There is also a lot of talks from Google I/O about optimizing apps that is worth checking out.

Google I/O 2009 - Writing Real-Time Games for Android Google I/O 2011 - Accelerated Android Rendering

Upvotes: 0

Related Questions