在AsyncTask中使用Cursor

时间:2012-04-09 04:50:22

标签: java android android-asynctask last.fm

我正在尝试为手机上有音乐的每位艺术家下载图像,然后在GridView中显示这些图像。我正在使用Last.fm建议使用的lastfm-java library。您调用以获取艺术家图像的方法是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的{​​{1}}并不特别,它只是扩展GridView

注意 AQuery是我正在使用的库,可帮助缓存并从网址加载BaseAdapter

Bitmap

完整之后,我的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();的{​​{1}}一个接一个地下载。换句话说,当我需要将它们放入position 0中的每个可用GridViewAdapter时,第一个position中的一个图像会加载,然后是下一个,依此类推。当我在我的position中返回我的测试GridView时,一切都会像它应该的那样。所有图像都按顺序放置在String[]的每个可用空间中。

问题

我的问题是,如何正确地将我下载的每个艺术家图片都归还AsyncTask?为什么这些图片目前仅在我GridView的第一个GridView处加载?< / p>

编辑 - Shubhayu的回答 我已将position设置为我的GridViewAdapter方法。这导致所有图像被下载(如LogCat所述),但只有最后一个图像在GridViewAdapter中设置。

getArtists()

smoak的回答 这会导致仅下载并应用到我的GridView中的最后一位艺术家图片(默认顺序)。

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

2 个答案:

答案 0 :(得分:1)

您的AsyncTask似乎每次为每个艺术家执行它。因此,您的AsyncTask只返回一位艺术家的图片,而您的GridView获得该艺术家图片,然后您为下一位艺术家运行AsyncTaskGridView更新了新图片,等等。你需要做的是修改你的AsyncTask以获取一个艺术家名字的String数组并在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();

答案 1 :(得分:1)

这是发生了什么,当你传递测试字符串时,它有一个图像列表,因此gridview正确地显示它们。但是当你用它为每位艺术家下载一张图片时,事情就出错了。

每次致电

  

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

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

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

修改

如果你看到AsyncTask,你会发现每次调用它时,字符串数组只返回一个图像。因此,不是返回字符串数组,而是返回一个字符串。

接下来,我建议您在Adapter中使用ArrayList而不是String数组。 在你的getArtists()中,每次调用

时都要创建一个ArrayList
  

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

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

现在将其设置为适配器。 (如果将其从字符串更改为arraylist,则不必更改适配器。)