我正在尝试从google books api调用生成一个android listview, google books api调用返回JSON数据,其中一个属性是图书缩略图的URL,所以我考虑运行第一个asynctask,它将调用JSON google books API然后onPostExecute我将运行第二个asynctask来获取缩略图并将它们设置为图像视图但是行为不正确并且缩略图与列表视图中的正确行没有关联,而只获取第一行中的图像视图时获取缩略图,并且当下载完成时,订单混乱。
以下是我的代码摘录:
private class BookSearchListAdapter extends BaseAdapter {
private ArrayList<Book> mBooks = new ArrayList<>();
private LayoutInflater mLayoutInflater;
public BookSearchListAdapter(Context c, ArrayList<Book> books) {
mLayoutInflater = LayoutInflater.from(c);
this.mBooks = books;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mLayoutInflater.inflate(R.layout.view_book_search_row, null);
holder = new ViewHolder();
holder.mImageView = (ImageView) convertView.findViewById(R.id.book_cover_thumbnail);
holder.mTitleTextView = (TextView) convertView.findViewById(R.id.book_title);
holder.mAuthorTextView = (TextView) convertView.findViewById(R.id.book_author);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Book b = mBooks.get(position);
holder.mAuthorTextView.setText(TextUtils.join(", ", b.getAuthors()));
holder.mTitleTextView.setText(b.getTitle());
if (!b.getThumbnail().equalsIgnoreCase("")) {
new ThumbNailDownloaderTask(holder.mImageView).execute(b.getThumbnail());
}
return convertView;
}
@Override
public int getCount() {
return mBooks.size();
}
@Override
public Object getItem(int position) {
return mBooks.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
}
private static class ViewHolder {
ImageView mImageView;
TextView mTitleTextView;
TextView mAuthorTextView;
}
private class SearchBookTask extends AsyncTask<String, Void, String> {
private final String TAG = "SearchBookTask";
private ArrayList<Book> mBooks = new ArrayList<>();
private final static String BOOK_ITEMS_KEY = "items";
private final static String BOOK_VOLUMEINFO_KEY = "volumeInfo";
private final static String BOOK_IMAGELINKS_KEY = "imageLinks";
private final static String BOOK_ID_KEY = "id";
private final static String BOOK_TITLE_KEY = "title";
private final static String BOOK_AUTHORS_KEY = "authors";
private final static String BOOK_DESCRIPTION_KEY = "description";
private final static String BOOK_THUMBNAIL_KEY = "thumbnail";
@Override
protected String doInBackground(String... params) {
String bookQuery = params[0];
String url = Uri.parse(ENDPOINT).buildUpon()
.appendQueryParameter("q", bookQuery)
.appendQueryParameter("maxResults", "10")
.appendQueryParameter("key", API_KEY)
.build().toString();
String result = new GoogleFetcher().getUrl(url);
return result;
}
@Override
protected void onPreExecute() {
mEmptyTextView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
}
@Override
protected void onPostExecute(String s) {
if (s != null) {
mProgressBar.setVisibility(View.GONE);
constructBooksFromJSONResponse(s);
mSearchResultListView.setAdapter(new BookSearchListAdapter(getActivity(), mBooks));
}
}
@Override
protected void onCancelled() {
mProgressBar.setVisibility(View.GONE);
}
private void constructBooksFromJSONResponse(String jsonResponse) {
try {
JSONObject obj = new JSONObject(new JSONTokener(jsonResponse));
JSONArray jsonArray = obj.getJSONArray(BOOK_ITEMS_KEY);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject currentObj = jsonArray.getJSONObject(i);
String bookId = "";
if (currentObj.has(BOOK_ID_KEY)) {
bookId = currentObj.getString(BOOK_ID_KEY);
}
JSONObject volumeInfo = currentObj.getJSONObject(BOOK_VOLUMEINFO_KEY);
String bookTitle = "";
if (volumeInfo.has(BOOK_TITLE_KEY)) {
bookTitle = volumeInfo.getString(BOOK_TITLE_KEY);
}
JSONArray bookAuthors = new JSONArray();
if (volumeInfo.has(BOOK_AUTHORS_KEY)) {
bookAuthors = volumeInfo.getJSONArray(BOOK_AUTHORS_KEY);
}
ArrayList<String> authors = new ArrayList<>();
if (bookAuthors != null) {
for (int j = 0; j < bookAuthors.length(); j++) {
authors.add(bookAuthors.getString(j));
}
}
String bookDescription = "";
if (volumeInfo.has(BOOK_DESCRIPTION_KEY)) {
bookDescription = volumeInfo.getString(BOOK_DESCRIPTION_KEY);
}
JSONObject imageLinks = volumeInfo.getJSONObject(BOOK_IMAGELINKS_KEY);
String bookThumbnail = "";
if (imageLinks.has(BOOK_THUMBNAIL_KEY)) {
bookThumbnail = imageLinks.getString(BOOK_THUMBNAIL_KEY);
}
Book b = new Book(bookId, authors, bookTitle, bookDescription, bookThumbnail);
mBooks.add(b);
}
} catch (JSONException e) {
mBooks.clear();
}
}
}
private class ThumbNailDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private ThumbNailDownloaderTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
@Override
protected Bitmap doInBackground(String... params) {
return downloadBitmap(params[0]);
}
private Bitmap downloadBitmap(String param) {
HttpURLConnection urlConnection = null;
try {
URL url = new URL(param);
urlConnection = (HttpURLConnection) url.openConnection();
int statusCode = urlConnection.getResponseCode();
if (statusCode != HttpURLConnection.HTTP_OK) {
return null;
}
InputStream in = urlConnection.getInputStream();
if (in != null) {
Bitmap bitmap = BitmapFactory.decodeStream(in);
return bitmap;
}
} catch (IOException e) {
if (urlConnection != null) {
urlConnection.disconnect();
}
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
return null;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
if (imageView != null) {
if (bitmap != null) {
imageView.setVisibility(View.VISIBLE);
imageView.setImageBitmap(bitmap);
}
}
}
}
}
和触发搜索的搜索按钮如下:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_addbook, container, false);
mSearchEditText = (EditText) v.findViewById(R.id.book_title_search_field);
mSearchButton = (Button) v.findViewById(R.id.search_button);
mSearchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String bookQuery = mSearchEditText.getText().toString();
new SearchBookTask().execute(bookQuery);
}
});
return v;
}
答案 0 :(得分:1)
您可以尝试使用Volley
ListView
库。获取有关image cache的更多信息。你可以找到体面的教程here和here。它应该能够正确加载{{1}}张图片。