关于Buttons和MediaPlayer的编码建议(避免编排跳过帧)

时间:2013-04-07 01:44:28

标签: android

我一直在制作一个关于我婴儿儿子声音的音板应用程序。该应用程序只是打开MainActivity类,它显示一个可滚动的按钮列表,当按下时,将播放我儿子尖叫的预先录制的MP3。

一旦在我的Nexus 7上调试或运行,就会出现Choreographer错误,并且会跳过介于50到90帧之间的错误。警告是'应用程序可能在其主线程上做了太多工作'。在我的设备上,三个随机按钮拒绝播放声音,直到应用程序关闭并重新打开,然后另外三个随机按钮拒绝工作。当我的应用程序在简单的LinearLayout(没有ScrollView)中只有八个按钮时,没有发生此问题。

我是java和Android编程的初学者但是,从我的猜测来看,我可笑的糟糕代码占用太多内存才能正常运行。我的问题是,你如何编写一个可滚动的33个按钮列表来播放自己的声音,或者有人可以教我如何更好地使用我的代码?

MainActivity.java(仅显示此问题的前三个按钮/声音):

import android.media.MediaPlayer;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.Button;
import android.view.View;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

final MediaPlayer ahh = MediaPlayer.create(this, R.raw.ahh);
final MediaPlayer dededeh = MediaPlayer.create(this, R.raw.dededeh);
final MediaPlayer neganegabunbunbug = MediaPlayer.create(this, R.raw.naganagbunbun);

Button bahh = (Button) this.findViewById(R.id.Ahhhbutton);
bahh.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        ahh.start();
    }
});
}
}

还有activity_main.xml(同样只有这个问题的前三个按钮):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tab1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin" >

<ScrollView
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <Button
            android:id="@+id/Ahhhbutton"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="5dp"
            android:background="@layout/button_shape"
            android:text="@string/button1a"
            android:textColor="#d1d1d1"
            android:textSize="20sp" />

        <Button
            android:id="@+id/dededehbutton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="5dp"
            android:background="@layout/button_shape"
            android:text="@string/button1b"
            android:textColor="#d1d1d1"
            android:textSize="20sp" />

        <Button
            android:id="@+id/neganegabunbunbugbutton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="5dp"
            android:background="@layout/button_shape"
            android:text="@string/button1c"
            android:textColor="#d1d1d1"
            android:textSize="20sp" />



Button bdededeh = (Button) this.findViewById(R.id.dededehbutton);
bdededeh.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        dededeh.start();
    }
});

Button bnaganagbunbun = (Button) this.findViewById(R.id.naganagabunbutton);
bnaganagbunbun.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        neganegabunbunbug.start();
    }
});

    </LinearLayout>
</ScrollView>

</LinearLayout>

1 个答案:

答案 0 :(得分:0)

这不是布局。正如您的错误所说,您不应该在主线程上进行任何长期工作。

主线程(或Android上的UI-Thread)处理与用户的交互。为了让UI不会冻结并感觉很快,您应该在UI-Thread上执行长期操作。

此外,问题不是实际播放,而是加载所有媒体文件:

MediaPlayer.create(this, R.raw.ahh);

正如create()-method的文档建议:

  

[...]完成MediaPlayer后,你应该调用release()来   释放资源。如果没有发布, MediaPlayer实例太多   将导致例外。

对于“关闭UI-Thread”的东西,你有三个选择:

  • 直接可以创建一个Runnable - 实现类来播放您的声音并将其提交到ScheduledThreadPoolExecuter(最大控件,更多代码)。
  • 使用AsyncTask(Android独家)播放歌曲(非常简单)。
  • 如果您希望即使应用当前不在前台也能继续播放声音,请使用Service(大部分工作)

所以,你应该做的是:

  1. 存储原始文件引用列表(R.raw.ahh)和直接加载它们。
  2. 选择播放歌曲时,请在该歌曲ID上调用create(),然后从UI-Thread开始播放。
  3. 完成后,请致电release()以释放资源。