您的位置:首页 > 移动开发 > Android开发

Android_AsyncTask详解及其应用(三)_图片错位以及AsyncTask重复创建的问题

2013-10-16 17:50 453 查看
http://blog.csdn.net/wangjinyu501/article/details/9008203

之前说了AsyncTask线程池的问题,接下来继续说一下AsyncTask应用上的有关问题。之前用豆瓣的API做应用的时候就发现一个问题,就是使用AsyncTask从豆瓣网站异步下载图片显示在ListView上面,会出现图片错位的现象。下面看一下那段代码:

[java] view
plaincopy

package com.android.douban.adapter;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.net.HttpURLConnection;

import java.net.MalformedURLException;

import java.net.URL;

import java.util.List;

import com.android.douban.R;

import com.android.douban.domain.Book;

import com.android.douban.util.LoadImageAsynTask;

import com.android.douban.util.LoadImageAsynTask.LoadImageAsynTaskCallback;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Bitmap.CompressFormat;

import android.graphics.BitmapFactory;

import android.net.Uri;

import android.os.AsyncTask;

import android.os.Environment;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.ImageView;

import android.widget.TextView;

public class BookInfoListAdapter extends BaseAdapter {

private Context mContext;

private List<Book> list;

private LayoutInflater inflater;

private TextView titleTextView, authorTextView, summeryTextView;

private ImageView bookImageView;

public Context getmContext() {

return mContext;

}

public void setmContext(Context mContext) {

this.mContext = mContext;

}

public BookInfoListAdapter(Context mContext, List<Book> list) {

super();

this.setmContext(mContext);

this.list = list;

}

@Override

public int getCount() {

return list.size();

}

@Override

public Object getItem(int arg0) {

return arg0;

}

@Override

public long getItemId(int arg0) {

return arg0;

}

@Override

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

ViewHolder holder = null;

View vi = convertView;

if (convertView == null) {

inflater = LayoutInflater.from(mContext);

vi = inflater.inflate(R.layout.activity_myread_listview_item, null);

holder.titleTextView = (TextView) vi

.findViewById(R.id.iv_book_title);

holder.authorTextView = (TextView) vi

.findViewById(R.id.iv_book_author);

holder.summeryTextView = (TextView) vi

.findViewById(R.id.iv_book_summary);

holder.bookImageView = (ImageView) vi.findViewById(R.id.img1);

} else {

holder = (ViewHolder) convertView.getTag();

}

holder.titleTextView.setText(list.get(position).getTitle());

holder.authorTextView.setText(list.get(position).getAuthor());

holder.summeryTextView.setText(list.get(position).getSummary());

String imageUrl = list.get(position).getBookImageUrl();

final String imageName = imageUrl.substring(

imageUrl.lastIndexOf("/") + 1, imageUrl.length());

File file = new File(Environment.getExternalStorageDirectory()

.getAbsolutePath() + "/" + imageName);

if (file.exists()) {

holder.bookImageView.setImageURI(Uri.fromFile(file));

System.out.println("使用SD卡缓存图片");

} else {

class AsyncTaskLoadImage extends AsyncTask<String, Integer, Bitmap> {

private ViewHolder holder;

public AsyncTaskLoadImage() {

holder=new ViewHolder();

}

@Override

protected void onPreExecute() {

super.onPreExecute();

}

@Override

protected Bitmap doInBackground(String... params) {

Bitmap bitmap = null;

try {

URL url = new URL(params[0]);

HttpURLConnection urlConnection = (HttpURLConnection) url

.openConnection();

urlConnection.connect();

int MAX = urlConnection.getContentLength();

InputStream inputStream = urlConnection

.getInputStream();

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

byte[] b = new byte[1024];

int len = 0;

while ((len = inputStream.read(b)) != -1) {

byteArrayOutputStream.write(b, 0, len);

}

bitmap = BitmapFactory.decodeByteArray(

byteArrayOutputStream.toByteArray(), 0, MAX);

inputStream.close();

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return bitmap;

}

@Override

protected void onPostExecute(Bitmap result) {

super.onPostExecute(result);

holder.bookImageView.setImageBitmap(result);

}

}

AsyncTaskLoadImage asyncTaskLoadImage = new AsyncTaskLoadImage();

asyncTaskLoadImage.execute(imageUrl);

}

return vi;

}

public class ViewHolder {

TextView titleTextView, authorTextView, summeryTextView;

ImageView bookImageView;

}

}

在这个自定义Adapter中,使用AsyncTask下载图片,然用一级缓存(保存图片到SD卡)。如果ListView显示的图片之前下载过,那么就从SD卡里面加载显示,不去下载,节省流量。表面上看没什么问题,但是实际使用中就会发现图片错位的现象。那图片为什么会错位呢?问题就在于

[java] view
plaincopy

if (convertView == null) {

} else {

holder = (ViewHolder) convertView.getTag();

}

重用了convertView导致的。如果你重用了convertView,此时convertView中的ImageView的id值是相等的,而我们在设置ImageView的图片时,是根据id来设置的,此时就出现了图片错位问题。 如果不重用convertView,在这种情况下,图片一般是不会产生错位的。但是你如果真的在使用这种方法来使用getView的话,并且图片量比较大的时候,你程序的性能肯定不会好到哪里去了。因此,重用convertView还是很有必要的。

那如何解决呢?android为我们提供了setTag()方法。具体做法是:在getView的时候给ViewHolder中的ImageView设置tag,其值为要放置在该ImageView上的图片的url地址。这个tag很重要,在异步下载图片完成回调的方法中,我们使用findViewWithTag(String url)来找到ListView中对应的ImagView,然后给该ImageView设置图片即可。在上面的代码中,就需要加入

[java] view
plaincopy

holder.bookImageView.setTag(list.get(position));

这段代码就可以了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐