0

AsyncTaskでデバイス上のすべての曲をフェッチしています。List変数Logのすべての曲が表示されると、それらすべてが表示されます。しかし、のコンストラクターでそれらを使用すると、常に空になります。これはどうして可能ですか?songsAsyncTaskLogArrayAdapter

AsyncTask:

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

したがって、private List<Song> songs変数はdoInBackground()AsyncTaskのメソッドに入力されますが、。では空になりonPostExecute()ます。

4

2 に答える 2

1

したがって、(アプリケーションの残りの部分を見ずに)あなたが見逃していると私が見ている重要なことは、次の呼び出しです。

songAdapter.notifyDataSetChanged();

もちろん、これはアダプタがBaseAdapterを拡張することを前提としています。その呼び出しがないと、アダプターはリストが更新されたことを知る方法がありません。したがって、リストを更新するときは常に「notifyDataSetChanged()」を呼び出すことをお勧めします。

必要に応じてCursorAdapterを使用することもできます。ビューはカーソルを呼び出して、データを自動的に取得する必要があります。マイレージはそれによって異なりますが、カーソルへのクエリが遅すぎると、ユーザーインターフェイスの速度が低下するためです。

他にもいくつか考えがあります。

  1. onPostExecute毎回新しいアダプタを作成しています。これは必要ありません。これは機能しますが、必須ではありません。プライベートリストをクリアしてから、アダプタsongsを呼び出すだけです。notifyDataSetChanged
  2. を呼び出すたびに、クリックリスナーを設定していますsongsList.setOnItemClickListener(new OnItemClickListener()。これも不要です。クリックリスナーは、onCreateまたはonResumeで設定できます。

これらは小さな詳細ですが、重要なことになります。新しいオブジェクトを作成して変数/メンバーに割り当てるたびに、プログラム内の別の場所で参照されていない限り、オブジェクトが置き換えるオブジェクトはガベージコレクションのマークが付けられます。これをやりすぎると、ガベージコレクターが時間外に動作し始め、アプリケーションの速度が低下します。特に、SongFinderタスクを頻繁に実行している場合はそうです。

お役に立てば幸いです。

于 2012-10-16T01:08:36.560 に答える
0

さて、私は実際にそれを理解しました。もう1つFragmentが同時にロードされていて、それもを使用していてEndlessSongAdapter、それがクラッシュしていました。私がすべてにコメントしたとき、他のすべてのコードはクラッシュすることなく実行および終了することができました....本当にばかげた間違い。LogCatは、実際には、どのフラグメントクラスから呼び出されているかをスタックトレースに表示していなかったため、わかりませんでした。

したがって、同じ問題が発生した場合は、ViewPager複数をロードしているFragmentsかどうか、およびそれらが「衝突」を引き起こす可能性があるかどうかを確認してください

于 2012-10-19T17:39:34.147 に答える