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

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

2013-07-05 20:24 721 查看
 之前说了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));  

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