我正在尝试为手机上有音乐的每位艺术家下载图像,然后在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);
答案 0 :(得分:1)
您的AsyncTask
似乎每次为每个艺术家执行它。因此,您的AsyncTask
只返回一位艺术家的图片,而您的GridView
获得该艺术家图片,然后您为下一位艺术家运行AsyncTask
,GridView
更新了新图片,等等。你需要做的是修改你的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()中,每次调用
时都要创建一个ArrayListnew LastfmArtistGetImageURL(test,mGridView,getActivity())。execute();
将结果添加到ArrayList。一旦您遍历了所有艺术家,您的ArrayList将包含所有图像。
现在将其设置为适配器。 (如果将其从字符串更改为arraylist,则不必更改适配器。)