【问题标题】:How do I make my animation smoother Android如何让我的动画更流畅 Android
【发布时间】:2012-02-17 01:30:07
【问题描述】:

我有一个应用程序有一个球在屏幕上运行。当球跑到一半时,应用程序会记录一些音频,计算 FFT 并进行一些额外的分析。

这是由 Asynctask 处理的,但是动画仍然会短暂卡顿。

有人对如何使其运行更顺畅有任何建议吗?

谢谢

代码如下:

import com.ben.applicationLayer.GameView;
import dataObjectLayer.Sprite;
import dataObjectLayer.MusicalNote;
import android.media.AudioRecord;
import android.media.MediaRecorder.AudioSource;
import android.media.AudioFormat; 
import android.os.AsyncTask;

public class recorderThread extends AsyncTask<Sprite, Void, Integer> {

short[] audioData;
int bufferSize;    
Sprite ballComp;

@Override
protected Integer doInBackground(Sprite... ball) {

    MusicalNote note = ball[0].expectedNote;
    ballComp = ball[0];
        boolean recorded = false; 
        double frequency;
        int sampleRate = 8192;  
        AudioRecord recorder = instatiateRecorder(sampleRate);
        double[] magnitude = new double[1024];
        double[] audioDataDoubles = new double[2048];

        while (!recorded) {  //loop until recording is running

        if (recorder.getState()==android.media.AudioRecord.STATE_INITIALIZED) 
// check to see if the recorder has initialized yet.
        {
            if (recorder.getRecordingState()==android.media.AudioRecord.RECORDSTATE_STOPPED)
                  recorder.startRecording();  
//check to see if the Recorder has stopped or is not recording, and make it record.                               
            else {             
               double max_index;
               recorder.read(audioData,0,bufferSize);   
//read the PCM audio data into the audioData array

               computeFFT(audioDataDoubles, magnitude);

               max_index = getLargestPeakIndex(magnitude);

               frequency = getFrequencyFromIndex(max_index, sampleRate);

            //checks if correct frequency, assigns number
               int correctNo = correctNumber(frequency, note);

checkIfMultipleNotes(correctNo, max_index, frequency, sampleRate, magnitude, note);

               if (audioDataIsNotEmpty())
                   recorded = true;
               if (correctNo!=1)
                   return correctNo;
              }
        }
        else
        {
            recorded = false;
            recorder = instatiateRecorder(sampleRate);
        }
    }

        if (recorder.getState()==android.media.AudioRecord.RECORDSTATE_RECORDING) 
        {
            killRecorder(recorder);
        }

        return 1;
}


private void killRecorder(AudioRecord recorder) {
    recorder.stop(); //stop the recorder before ending the thread
    recorder.release(); //release the recorders resources
    recorder=null; //set the recorder to be garbage collected
}

@Override
protected void onPostExecute(Integer result) {  
    (result == 2)
        GameView.score++;
    }

private AudioRecord instatiateRecorder(int sampleRate) {    
        bufferSize= AudioRecord.getMinBufferSize(sampleRate,AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT)*2;
 //get the buffer size to use with this audio record

AudioRecord recorder = new AudioRecord (AudioSource.MIC,sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,bufferSize); //instantiate the AudioRecorder

    audioData = new short [bufferSize]; //short array that pcm data is put into.         
        return recorder;
}

}

【问题讨论】:

  • 向我们展示调用此 AsyncTask 的代码,因为问题不在这里。 AsyncTask 在不同的线程上完成它的工作,因此它不应该影响动画(在概念上,但如果这是极端的话可能会)。无论如何,请向我们展示动画代码和调用此 AsyncTask 的位置

标签: java android multithreading android-asynctask ondraw


【解决方案1】:

使用 Asynctask 符合您的要求。但是,我建议使用线程池。然后,您可以将您的动画作为一项任务添加,将您的录音添加为一项任务,将 FFT 作为另一项任务添加,并将您的附加分析作为一项任务添加。

短暂的卡顿很可能是为动画线程中的录制分配资源的结果。使用池意味着您在创建线程以运行音频任务时不必暂停。显然,一些代码可以方便地完全理解您的问题。

看看:

ScheduledThreadPoolExecutor http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html

线程池执行器 http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html

您可能想做的一个非常简单的例子:

在您的活动中,您可以定义它来启动任务

ExecutorService threadPool = new ScheduledThreadPoolExecutor(2);
Recording record = new Recording();
Ball ball = new Ball(threadPool, record);
threadPool.submit(ball);

球.java

import java.util.concurrent.ExecutorService;

public class Ball implements Runnable { 
    private final Recording record;
    private final ExecutorService threadPool;

    private boolean condition;  
    private boolean active;

    public Ball(ExecutorService threadPool, Recording record) {
        this.record = record;
        this.threadPool = threadPool;
        this.active = true;
    }

    @Override public void run() {
        while (this.active) {
            moveBall();
            if (isBallHalfway()) {
                threadPool.submit(record);
            }
        }
    }

    private boolean isBallHalfway() {
        return condition; // Condition for determining when ball is halfway
    }

    private void moveBall() {
        // Code to move the ball
    }
}

Recording.java

public class Recording implements Runnable {
    @Override public void run() {
        // Do recording tasks here
    }
}

【讨论】:

  • 我已包含代码,感谢您的回复。查看代码,您认为哪种类型的线程最好?
  • 抱歉耽搁了,我添加了一些代码来展示如何使用线程池解决问题。这应该给您一个想法,如果您需要进一步解释,请随时提出更多问题。 :)
【解决方案2】:

正如 Mohammed 所说,不看代码就很难猜出问题所在。考虑到这一点...

听起来您的AsyncTask 可能会阻止其他线程执行。确保你在那里调用了Thread.sleep(),让调度程序有机会切换回 UI 线程(Thread.yield() 也是一个选项,但请注意有一些与 yield 相关的问题)。

【讨论】:

  • 我现在已经包含了代码,我应该在哪里包含睡眠方法?我应该为产量烦恼吗?
  • 如果您完全不确定自己在做什么,最好避免使用 yield。在不知道这些方法调用中的每一个需要多长时间的情况下,我不得不猜测,但我会说将调用放在sleep 的一个很好的候选者将在你的 while 循环结束时。如果computeFFT() 函数很慢(它可能“很快”,但如果内存服务于 FFT 仍然涉及大量工作),您可能还想看看在其中对sleep() 进行一些调用。
【解决方案3】:

如果没有代码,使用 can optimize 将很难猜测,但我会告诉你我在加载超过 100 万次操作时做了什么.. • 如果您遇到性能问题,请尝试: 1-检查变量的数据类型并设置较低,以防您确定变量不需要更多字节,即对于您的大小而不是 int。

2-检查您的代码并尝试将所有结果存储起来以供下次启动,并在下次调用它们而不是再次计算它们。

• 但是如果你的问题是动画慢而且你的记忆力没有问题,那么请尝试减少动画周期或增加运动单位。

顺便问一下,你是如何实现动画的?逐帧动画,还是布局动画,还是视图动画?

【讨论】:

  • 如果您正在优化速度,#1 实际上是个坏主意! JVM 在执行任何算术运算之前将字节、short 和 char 转换为整数,因此使用例如shorts 充其量是相同的,最坏的情况是比使用 int 慢。
  • 你是对的,我也是......我提到了存储效率,而你在谈论运行时性能。所以在我们的同胞 Ben Taliadoros 的情况下,我同意你的观点 :-) 用户较低的数据类型没有什么大不了的……+ 到你的评论 Baqueta,thnx 获取信息
  • 感谢您的回复,很有趣。我现在已经包含了我的代码,以逐帧向您展示,以回答您的问题 Mohammed。有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-12
  • 2018-03-16
  • 1970-01-01
  • 2013-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多