ArrayAdapter数据列表始终为空,尽管它在AsyncTask中已满

时间:2012-10-16 00:44:11

标签: android android-asynctask android-arrayadapter

我正在AsyncTask中获取设备上的所有歌曲。当我Log songs中的AsyncTask列表变量中的所有歌曲都显示出来时Log。但是当我在ArrayAdapter的构造函数中private class SongFinder extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... params) { ContentResolver resolver = activity.getContentResolver(); Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; Cursor cursor = resolver.query(uri, projection, selection, null, null); Log.i(TAG, "Fetching next batch of songs"); if (cursor == null) { Toast.makeText(activity, "Failed to discover songs", Toast.LENGTH_LONG).show(); } else if (!cursor.moveToFirst()) { Toast.makeText(activity, "No media on device", Toast.LENGTH_LONG).show(); } else { cursor.moveToFirst(); while (cursor.moveToNext()) { String id = cursor.getString(0); String title = cursor.getString(2); String artist = cursor.getString(1); String data = cursor.getString(3); String albumName = cursor.getString(8); Long albumId = cursor.getLong(6); String albumKey = cursor.getString(7); songs.add(new Song(id, title, artist, data, albumName, albumKey, albumId)); } } cursor.close(); // HERE IT'S FULL WITH THE SONGS I WANT Log.d(TAG, songs.toString()); return null; } @Override protected void onPostExecute(Void result) { if (songs.size() > 0) { //HERE IT IS ALWAYS EMPTY Log.d(TAG, songs.toString()); SongArrayAdapter adapter = new SongArrayAdapter(activity, songs); EndlessSongAdapter songAdapter = new EndlessSongAdapter(activity, adapter, R.layout.arrayadapter_songs); songsList.setAdapter(songAdapter); songsList.setTextFilterEnabled(true); songsList.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> root, View view, int position, long when) { Intent newSong = new Intent(MusicService.ACTION_NEW); newSong.putExtra("song", songs.get(position)); Log.i(TAG, "sending broadcast"); bManager.sendBroadcast(newSong); // Reset the play/pause button. activity.resetButton(); Intent addSong = new Intent( "com.xx.xx.ADDSONG"); addSong.putExtra("song", songs.get(position)); bManager.sendBroadcast(addSong); activity.fragmentChangeNewSong(); } }); } } } 时,它总是空的。这怎么可能呢?

AsyncTask:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    activity = (MusicActivity) getActivity();
    bManager = LocalBroadcastManager.getInstance(activity);
    ListView songsList = getListViewWithSongs(activity);
    return songsList;
}

public ListView getListViewWithSongs(final MusicActivity activity) {
    songsList = new ListView(activity);
    new SongFinder().execute();

    return songsList;
}

修改

调用AsyncTask

private List<Song> songs

因此doInBackground()变量填入了AsyncTask的onPostExecute()方法,但它在{{1}}中为空。

2 个答案:

答案 0 :(得分:1)

所以,我看到你丢失的重要事情(没有看过应用程序的其余部分),是打电话给:

songAdapter.notifyDataSetChanged();

这假定您的适配器扩展了BaseAdapter。没有该调用,适配器无法知道列表已更新。所以,每当你更新列表时总是调用'notifyDataSetChanged()'是个好主意。

如果您愿意,也可以使用CursorAdapter,视图应该调用光标自动获取数据。但是,您的里程会因此而异,因为如果对光标的查询太慢,则用户界面会变慢。

以下是其他一些想法:

  1. onPostExecute中,您每次都在创建一个新的适配器。这不是必需的。这有效,但没有必要。您只需清除私人列表songs,然后在适配器上调用notifyDataSetChanged即可。
  2. 每次拨打songsList.setOnItemClickListener(new OnItemClickListener()时,您都会设置点击监听器。这也是不必要的。您可以在onCreate或onResume上设置单击侦听器。
  3. 这些是小细节,但它们加起来很重要。每次创建新对象并将其分配给变量/成员时,它替换的对象都会标记为垃圾回收,除非它被引用到程序中的其他位置。如果你这样做太多,垃圾收集器将开始加班并减慢你的应用程序 - 特别是如果你经常运行SongFinder任务。

    希望有所帮助。

答案 1 :(得分:0)

嗯,我真的想通了。另一个Fragment同时被加载,它也使用了EndlessSongAdapter并且崩溃了它。当我评论这一切时,所有其他代码都能够运行并完成,而不会崩溃....真的很愚蠢的错误。 LogCat实际上没有在Stack跟踪中显示它被调用的片段类,所以我从来没有想过它

因此,如果您遇到同样的问题,请检查您的ViewPager是否加载多个Fragments以及是否可能造成“碰撞”