TextView.setText导致强制关闭内部catch(但不是其他)

时间:2012-12-03 03:32:01

标签: android android-widget

我正在尝试编写一个简单的应用程序来尝试加载和播放声音文件。我有两个声音,我想得到它们的列表,然后回放点击的任何一个。以下代码有效:

public class SoundPoolTest extends ListActivity {
    String sounds[] = { "shot", "explode" };
    SoundPool soundPool;
    int[] soundId = new int[sounds.length];
    {
        for (int i = 0; i < soundId.length; i++) {
            soundId[i] = -1;
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        setVolumeControlStream(AudioManager.STREAM_MUSIC);
        soundPool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);

        super.onCreate(savedInstanceState);
        setListAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, sounds));
        for (int i = 0; i < sounds.length; i++) {

            try {
                AssetManager assetManager = getAssets();
                AssetFileDescriptor descriptor = assetManager.openFd("sound/"
                        + sounds[i] + ".wav");
                soundId[i] = soundPool.load(descriptor, 1);
            } catch (IOException e) {
                TextView textView = (TextView) super.getListView()
                        .getChildAt(i);
                textView.setText("Could not load file!");
            }
        }
    }

    protected void onListItemClick(ListView list, View view, int position,
            long id) {
        super.onListItemClick(list, view, position, id);
        if (soundId[position] != -1) {
            soundPool.play(soundId[position], 1, 1, 0, 0, 1);
        }
    }
}

但是,如果我弄乱assetManager.openFd的参数以便找不到文件来测试异常处理程序,则应用程序强制在呈现列表之前关闭(LogCat输出thread exiting with uncaught exception)。问题是textView.setText("Could not load file!");行;如果我评论它没有问题。更令人费解的是,如果我将catch留空并将相同的代码放入onListItemClick方法,那么它看起来像这样

protected void onListItemClick(ListView list, View view, int position,
            long id) {
        super.onListItemClick(list, view, position, id);
        TextView textView = (TextView) super.getListView().getChildAt(position);
        textView.setText("Clicked!");
        if (soundId[position] != -1) {
            soundPool.play(soundId[position], 1, 1, 0, 0, 1);
        }
    }

它运行正常,在按预期点击时更改文本。我无法理解这种行为。

2 个答案:

答案 0 :(得分:0)

问题可能是super.getListView().getChildAt(i); ListView不会维护所有创建的子视图。它仅保留对屏幕上视图的引用。屏幕外的视图将被回收并重新用于其他内容。如果底层数据很大,这就避免了必须管理数百个视图。

尝试从适配器中的getView()方法加载声音。一般情况下,请避免尝试暂停ListView以外的getView()项目。

答案 1 :(得分:0)

在你的for()循环中进行此更改,然后尝试。

for (int i = 0; i < sounds.length; i++) {

        try {
            AssetManager assetManager = getAssets();
            AssetFileDescriptor descriptor = assetManager.openFd("sound/"
                    + sounds[i] + ".wav");
            TextView textView = (TextView) super.getListView()
                    .getChildAt(i);
            soundId[i] = soundPool.load(descriptor, 1);
        } catch (IOException e) {
            textView.setText("Could not load file!");
        }
    }