TextView.setText导致强制关闭内部捕捉(但不是)

问题描述:

我想写一个简单的应用程序来尝试加载和播放声音文件。我有两个声音,我想要得到它们的列表,然后播放哪个被点击。下面的代码工作:TextView.setText导致强制关闭内部捕捉(但不是)

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); 
     } 
    } 
运行良好

,点击时按预期改变的文本。我无法理解这种行为。

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

尝试将getView()方法中的声音加载到适配器中。一般而言,请避免试图从getView()以外的地方获得ListView物品。

+0

你的意思只是调用'super.getListAdapter.getView()'或更精细的东西吗?如果是前者,我无法理解官方文件;它只是给出语法'公共视图getView(int位置,视图convertView,ViewGroup父)',我不知道我应该给它作为'convertView'参数。 – kuoytfouy

+0

您不必调用getViez()。系统为列表中的每个项目调用getView()。因此,你的try/catch块应该在getView() – znat

在for 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!"); 
     } 
    } 
+0

这样变量'textView'甚至不在'try'块外面。 – kuoytfouy

+0

尝试将textView声明为全局。 – AndroidLearner