1

携帯電話に音楽を保存しているアーティストごとに画像をダウンロードして、これらの画像をに表示しようとしていますGridView。Last.fmが推奨するlastfm-javaライブラリを使用しています。アーティストの画像を取得するために呼び出すメソッドはですがgetImageURL(ImageSize size)、これを行う前に、パラメータを使用して参照するアーティストを指定する必要がありStringます。したがって、完全には次のようになります。

@Override
protected String doInBackground(Object... arg0) {
    Artist artist = Artist.getInfo(artistOrMbid, LASTFM_API_KEY);
    return artist.getImageURL(ImageSize.EXTRALARGE);      
}

私の電話にいるすべてのアーティストを取得することは問題ではありません、あなたはただ参照しますMediaStore。あなたはこのようなことをするでしょう:

private void getArtists() {
    String[] projection = new String[] {
            MediaStore.Audio.Artists._ID, MediaStore.Audio.Artists.ARTIST,
    };
    String sortOrder = MediaStore.Audio.Artists.DEFAULT_SORT_ORDER;
    Cursor c = getActivity().getContentResolver().query(
            MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, projection, null, null, sortOrder);
    if (c != null) {
        int count = c.getCount();
        if (count > 0) {
            final int ARTIST_IDX = c.getColumnIndex(MediaStore.Audio.Artists.ARTIST);
            for (int i = 0; i < count; i++) {
                c.moveToPosition(i);
            }
        }
        c.close();
        c = null;
    }
}

Adapter私にとってはGridView特別なことではなく、単に拡張するだけBaseAdapterです。

AQueryは私が使用しているライブラリでありBitmap、URLからのキャッシュとロードに役立ちます。

public class GridViewAdapter extends BaseAdapter {

private final String[] imageURLs;

private final LayoutInflater mInflater;

private final Activity mActivity;

public GridViewAdapter(String[] urls, Activity activity) {
    imageURLs = urls;
    mActivity = activity;
    mInflater = (LayoutInflater)mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public int getCount() {
    return imageURLs.length;
}

@Override
public Object getItem(int position) {
    return position;
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    ViewHolder viewholder = null;

    // Inflate GridView items
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.gridview_items, null);
        viewholder = new ViewHolder();
        viewholder.mImage = (ImageView)convertView.findViewById(R.id.gridview_image);
        convertView.setTag(viewholder);
    } else {
        viewholder = (ViewHolder)convertView.getTag();
    }

    AQuery aq = new AQuery(convertView);

    aq.id(viewholder.mImage).image(imageURLs[position], false, false, 0, 0, null, 0, 0.75f);

        return convertView;
    }

}

class ViewHolder {
    public ImageView mImage;
}

完全に、私のAsyncTaskは次のとおりです。

public class LastfmArtistGetImageURL extends AsyncTask<Object, Integer, String[]> implements
    Constants {

private static final String tag = LastfmArtistGetImageURL.class.getSimpleName();

private GridViewAdapter mGridAdapter;

// Test
private final String[] imageIds = {
        "http://userserve-ak.last.fm/serve/252/71875544.png",
        "http://userserve-ak.last.fm/serve/252/6258507.jpg",
        "http://userserve-ak.last.fm/serve/252/51274303.png",
        "http://userserve-ak.last.fm/serve/252/58672183.png",
        "http://userserve-ak.last.fm/serve/252/72029714.png",
        "http://userserve-ak.last.fm/serve/252/17666215.jpg",
        "http://userserve-ak.last.fm/serve/252/63247381.png",
        "http://userserve-ak.last.fm/serve/252/33665463.jpg"
};

private final String artistOrMbid;

private final GridView mGridView;

private final Activity mActivity;

public LastfmArtistGetImageURL(String name, GridView gv, Activity activity) {
    artistOrMbid = name;
    mGridView = gv;
    mActivity = activity;
}

@Override
protected String[] doInBackground(Object... arg0) {
    Artist artist = Artist.getInfo(artistOrMbid, LASTFM_API_KEY);
    Collection<String> col = new ArrayList<String>();
    col.add(artist.getImageURL(ImageSize.EXTRALARGE));
    return col.toArray(new String[0]);
}

@Override
protected void onPostExecute(String[] result) {
    if (result != null)
        mGridAdapter = new GridViewAdapter(imageIds, mActivity);
    mGridView.setAdapter(mGridAdapter);
    super.onPostExecute(result);
    }
}

を呼び出すときはAsyncTask、次のgetArtists()ようにメソッドで呼び出します。

new LastfmArtistGetImageURL(c.getString(ARTIST_IDX), mGridView, getActivity()) .execute();

問題

position 0これを呼ぶと、すべてのアーティストの画像がダウンロードされますが、私のでは次々にダウンロードされますGridViewAdapter。つまり、1つの画像が読み込まれ、次に次の画像が読み込まれます。最初に、でposition使用可能なそれぞれの画像に画像を配置する必要があります。テストを返すと、すべてが正常に機能します。すべての画像は、の使用可能な各スペースに順番に配置されます。positionGridViewString[]AsyncTaskGridView

質問

私の質問は、ダウンロードした各アーティストの画像をGridView正しく返すにはどうすればよいですか。また、現在、画像が最初positionにのみ読み込まれているのはなぜGridViewAdapterですか。

編集-Shubhayuの答え 私はGridViewAdapter自分のgetArtists()方法をそのように設定するように移動しました。これにより、すべての画像がダウンロードされますが(LogCatによると)、最後の画像のみが私のに設定されますGridView

String[] test = new LastfmArtistGetImageURL(c.getString(ARTIST_IDX),
mGridView, getActivity()).execute().get();
mGridAdapter = new GridViewAdapter(test, getActivity());
mGridView.setAdapter(mGridAdapter);

smoakの回答 これにより、最後のアーティスト画像(デフォルトの順序)のみがダウンロードされ、私のに適用されますGridView

String[] test = {c.getString(ARTIST_IDX)};
new LastfmArtistGetImageURL(test, mGridView, getActivity()).execute();
4

2 に答える 2

1

アーティストAsyncTaskごとに毎回実行しているように見えます。したがって、あなたAsyncTaskは1人のアーティストの画像のみを返し、そのアーティストの画像を取得し、次のアーティストGridViewのためにを実行し、新しい画像で更新されます。あなたがする必要があるのは、アーティスト名の文字列配列を取得し、それらをループして画像を取得するように変更することです。AsyncTaskGridViewAsyncTaskdoInBackground

// ... SNIPPED

public LastfmArtistGetImageURL(String[] names, GridView gv, Activity activity) {
    artistsOrMbids = names;
    mGridView = gv;
    mActivity = activity;
}

@Override
protected String[] doInBackground(Object... arg0) {
    Collection<String> col = new ArrayList<String>();
    for (String nameOrMbid : this.artistsOrMbids) {
        Artist artist = Artist.getInfo(artistOrMbid, LASTFM_API_KEY);
        col.add(artist.getImageURL(ImageSize.EXTRALARGE));
    }
    return col.toArray(new String[0]);
}


// .... SNIPPED

そして、すべてのアーティスト名を渡します。

String[] artists = { "The Black Keys", "Rush", "The Allman Brothers" }; 
new LastfmArtistGetImageURL(artists, mGridView, getActivity()).execute();
于 2012-04-09T05:44:26.793 に答える
1

これが起こっていることです。テスト文字列に合格すると、画像のリストが表示されるため、グリッドビューに画像が正しく表示されます。しかし、それを使用して各アーティストの画像をダウンロードすると、問題が発生します。

電話をかけるたびに

新しいLastfmArtistGetImageURL(c.getString(ARTIST_IDX)、mGridView、getActivity())。execute();

doInBackground()を実行して完了し、すぐにonPostExecute()を呼び出して、新しいアダプターを作成し、基本的に単一の呼び出しの単一のイメージを含む結果を渡します。

したがって、必要なのは、非同期タスクですべてのイメージをダウンロードしてから、単一のアダプターを作成して、すべてのイメージをそれに渡すことです。それは現在起こっていません。

編集

AsyncTaskを見ると、それを呼び出すたびに、文字列配列が1つの画像のみを返すことがわかります。したがって、文字列配列を返す代わりに、文字列を返します。

次に、アダプタで文字列配列の代わりにArrayListを使用することをお勧めします。getArtists()で、ArrayListを作成し、呼び出すたびに

new LastfmArtistGetImageURL(test、mGridView、getActivity())。execute();

結果をArrayListに追加します。すべてのアーティストをループすると、ArrayListにすべての画像が含まれます。

次に、アダプタに設定します。(アダプタを文字列から配列リストに変更する場合は、アダプタを少し変更する必要はありません。)

于 2012-04-09T05:48:17.897 に答える