1

我一直在为我的婴儿儿子的声音制作一个音板应用程序。该应用程序只是打开到 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>
4

1 回答 1

0

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

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

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

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

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

[...] 完成 MediaPlayer 后,您应该调用 release() 来释放资源。如果不释放,过多的 MediaPlayer 实例将导致异常。

对于“关闭 UI 线程”,您有三个选项:

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

所以,你应该做的是:

  1. 存储原始文件引用的列表(R.raw.ahh),不要直接加载它们。
  2. When a song is selected for playback, call create()on that songs ID and start playback off the UI-Thread.
  3. 完成后,调用release()释放资源。
于 2013-04-07T02:14:11.930 回答