0

我在 AsyncTask 中获取设备上的所有歌曲。当我在List 变量中的Log所有歌曲都显示出来时。但是当我在它们的构造函数中时,它总是空的。这怎么可能?songsAsyncTaskLogArrayAdapter

异步任务:

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();
                }

            });
        }
    }
}

编辑

调用异步任务

@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;
}

所以这个private List<Song> songs变量在doInBackground()AsyncTask的方法里面是填的,但是在onPostExecute().

4

2 回答 2

1

所以,我看到你失踪的关键事情(没有看到应用程序的其余部分)是调用:

songAdapter.notifyDataSetChanged();

这当然假设您的适配器扩展了 BaseAdapter。如果没有该调用,适配器将无法知道列表已更新。因此,每次更新列表时始终调用“notifyDataSetChanged()”是个好主意。

如果你愿意,你也可以使用 CursorAdapter,视图应该调用游标来自动获取数据。但是,您的里程会有所不同,因为如果对光标的查询太慢,用户界面就会变慢。

以下是其他一些想法:

  1. onPostExecute你每次都在创建一个新的适配器。这是没有必要的。这有效,但不是必需的。您可以简单地清除私有列表songs,然后调用notifyDataSetChanged适配器。
  2. 每次调用时,您都在设置 on click 侦听器songsList.setOnItemClickListener(new OnItemClickListener()。这也是不必要的。您可以在 onCreate 或 onResume 中设置点击监听器。

这些都是小细节,但它们加起来很重要。每次创建新对象并将其分配给变量/成员时,它所替换的对象都会被标记为垃圾回收,除非它在程序中的其他地方被引用。如果你这样做太多,垃圾收集器将开始加班并减慢你的应用程序 - 特别是如果你经常运行你的SongFinder任务。

希望有帮助。

于 2012-10-16T01:08:36.560 回答
0

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

因此,如果您遇到同样的问题,请检查您ViewPager是否正在加载多个Fragments以及它们是否可以创建“碰撞”

于 2012-10-19T17:39:34.147 回答