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

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

2013-06-02 20:14 609 查看
之前说了AsyncTask线程池的问题,接下来继续说一下AsyncTask应用上的有关问题。之前用豆瓣的API做应用的时候就发现一个问题,就是使用AsyncTask从豆瓣网站异步下载图片显示在ListView上面,会出现图片错位的现象。下面看一下那段代码: [java] view plaincopypackage 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 plaincopyif (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 plaincopyholder.bookImageView.setTag(list.get(position));
这段代码就可以了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐