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

Adapterfor myGridView没什么特别的,它只是扩展了BaseAdapter.

注意 AQuery是我正在使用的一个库,它可以帮助缓存和加载Bitmap来自 URL 的 a。

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

当我调用 myAsyncTask时,我在我的getArtists()方法中调用它,如下所示:

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

问题

当我调用这个时,所有艺术家的图像都会下载,但他们会一个接一个地下载position 0我的GridViewAdapter. 换句话说,一个图像加载,然后是下一个,等等,position当我需要将它们放入每个可用positionGridView. 当我返回我的测试String[]时,我的AsyncTask一切都正常工作。所有图像都按顺序放置在GridView.

问题

我的问题是,如何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只返回一个艺术家的图像并GridView获得该艺术家的图像,然后AsyncTask为下一个艺术家运行,GridView使用新图像进行更新等等。您需要做的是修改您AsyncTask的字符串数组,以获取艺术家姓名并在它们中循环doInBackground以获取他们的图像。

// ... 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

这就是正在发生的事情,当您通过测试字符串时,它有一个图像列表,因此 gridview 可以正确显示它们。但是当您使用它为每个艺术家下载图像时,事情就会出错。

每次打电话

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

它运行 doInBackground(),完成它,然后立即调用 onPostExecute() 在其中创建一个新适配器并传递您的结果,该结果基本上包含单个调用的单个图像。

所以你需要做的是在你的异步任务中下载所有图像,然后创建一个适配器并将所有图像传递给它。目前还没有发生这种情况。

编辑

如果您看到 AsyncTask,您会发现每次调用它时,字符串数组都只返回一张图像。所以不是返回一个字符串数组,而是返回一个字符串。

接下来,我建议您在适配器中使用 ArrayList 而不是 String 数组。在您的 getArtists() 中,创建一个 ArrayList 并在您每次调用时

new LastfmArtistGetImageURL(test, mGridView, getActivity()).execute();

将结果添加到您的 ArrayList。遍历所有艺术家后,您的 ArrayList 将包含所有图像。

现在将其设置为适配器。(如果将适配器从字符串更改为数组列表,则无需稍微更改适配器。)

于 2012-04-09T05:48:17.897 回答