我正在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}}中为空。
答案 0 :(得分:1)
所以,我看到你丢失的重要事情(没有看过应用程序的其余部分),是打电话给:
songAdapter.notifyDataSetChanged();
这假定您的适配器扩展了BaseAdapter。没有该调用,适配器无法知道列表已更新。所以,每当你更新列表时总是调用'notifyDataSetChanged()'是个好主意。
如果您愿意,也可以使用CursorAdapter,视图应该调用光标自动获取数据。但是,您的里程会因此而异,因为如果对光标的查询太慢,则用户界面会变慢。
以下是其他一些想法:
onPostExecute
中,您每次都在创建一个新的适配器。这不是必需的。这有效,但没有必要。您只需清除私人列表songs
,然后在适配器上调用notifyDataSetChanged
即可。songsList.setOnItemClickListener(new OnItemClickListener()
时,您都会设置点击监听器。这也是不必要的。您可以在onCreate或onResume上设置单击侦听器。这些是小细节,但它们加起来很重要。每次创建新对象并将其分配给变量/成员时,它替换的对象都会标记为垃圾回收,除非它被引用到程序中的其他位置。如果你这样做太多,垃圾收集器将开始加班并减慢你的应用程序 - 特别是如果你经常运行SongFinder
任务。
希望有所帮助。
答案 1 :(得分:0)
嗯,我真的想通了。另一个Fragment
同时被加载,它也使用了EndlessSongAdapter
并且崩溃了它。当我评论这一切时,所有其他代码都能够运行并完成,而不会崩溃....真的很愚蠢的错误。 LogCat实际上没有在Stack跟踪中显示它被调用的片段类,所以我从来没有想过它
因此,如果您遇到同样的问题,请检查您的ViewPager
是否加载多个Fragments
以及是否可能造成“碰撞”