android開發中解決ListView非同步載入圖片錯亂問題

來源:互聯網
上載者:User
 代碼如下 複製代碼

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * 非同步圖片控制項
 * 使用:new AsyncImageView().asyncLoadBitmapFromUrl("http://xxxx","緩衝路徑"){
 *
 * @author gaoomei@gmail.com
 * @site http://obatu.sinaapp.com
 * @version 1.0
 * @2011-12-3
 */
public class AsyncImageView extends ImageView {

 /**
  * 非同步task載入器
  */
 private AsyncLoadImage mAsyncLoad;

 /**
  * 下載回來的圖片緩衝存活時間,單位:秒(s),預設30分鐘
  */
 private long mCacheLiveTime = 1800;

 public AsyncImageView(Context context) {
  super(context);
 }

 public AsyncImageView(Context context, AttributeSet attrs) {
  super(context, attrs);
 }

 public AsyncImageView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
 }

 /**
  *
  */
 @Override
 public void setImageDrawable(Drawable drawable) {
  if (mAsyncLoad != null) {
   mAsyncLoad.cancel(true);
   mAsyncLoad = null;
  }
  super.setImageDrawable(drawable);
 }

 /**
  * 重寫下面幾個設定圖片資源的方法,目地是取消網路載入
  */
 @Override
 public void setImageResource(int resId) {
  cancelLoad();
  super.setImageResource(resId);
 }

 @Override
 public void setImageURI(Uri uri) {
  cancelLoad();
  super.setImageURI(uri);
 }

 @Override
 public void setImageBitmap(Bitmap bitmap) {
  cancelLoad();
  super.setImageBitmap(bitmap);
 }

 /**
  * 取消進行中的非同步task
  */
 public void cancelLoad() {
  if (mAsyncLoad != null) {
   mAsyncLoad.cancel(true);
   mAsyncLoad = null;
  }
 }

 /**
  * 設定圖片存活時間
  *
  * @param second
  *            存活時間,單位【秒】,如果等於0或null,則不緩衝
  */
 public void setCacheLiveTime(long second) {
  if (second == 0) {
   this.mCacheLiveTime = 0;
  } else if (second >= 0) {
   this.mCacheLiveTime = second * 1000;
  }
 }

 /**
  * 從網路非同步載入
  *
  * @param url
  * @param saveFileName
  */
 public void asyncLoadBitmapFromUrl(String url, String saveFileName) {
  if (mAsyncLoad != null) {
   mAsyncLoad.cancel(true);
  }
  // AsyncTask不可重用,所以每次重新執行個體
  mAsyncLoad = new AsyncLoadImage();
  mAsyncLoad.execute(url, saveFileName);
 }

 /**
  * 非同步載入器
  */
 private class AsyncLoadImage extends AsyncTask {
  /**
   * 是否取消
   */
  private boolean isCancel = false;

  @Override
  protected Bitmap doInBackground(String... params) {
   if (isCancel) {
    return null;
   }
   String url = params[0];
   String fileName = params[1];
   try {
    return getBitmap(url, fileName);
   } catch (IOException e) {
    e.printStackTrace();
   }
   return null;
  }

  @Override
  protected void onCancelled() {
   System.out.println("async load imgae cancel");
   isCancel = true;
  }

  @Override
  protected void onPostExecute(Bitmap result) {
   if (!isCancel && result != null) {
    AsyncImageView.this.setImageBitmap(result);
   }
  }
 }

 /**
  * 下載圖片
  *
  * @param urlString
  *            url下載地址
  * @param fileName
  *            快取檔案路徑
  * @throws IOException
  */
 private Bitmap getBitmap(String urlString, String fileName)
   throws IOException {
  if (fileName == null || fileName.trim().isEmpty()) {
   InputStream input = getBitmapInputStreamFromUrl(urlString);
   return BitmapFactory.decodeStream(input);
  }

  File file = new File(fileName);
  if (!file.isFile()
    || (mCacheLiveTime > 0 && (System.currentTimeMillis()
      - file.lastModified() > mCacheLiveTime))) {
   InputStream input = getBitmapInputStreamFromUrl(urlString);
   file = saveImage(input, fileName);
   // 如果檔案結構建立失敗,則直接從輸入資料流解碼圖片
   if (file == null || !file.exists() || !file.canWrite()
     || !file.canRead()) {
    return BitmapFactory.decodeStream(input);
   }
  }
  return BitmapFactory.decodeFile(file.getAbsolutePath());
 }

 /**
  * 下載圖片,輸入InputStream
  *
  * @param urlString
  * @return
  * @throws IOException
  */
 private InputStream getBitmapInputStreamFromUrl(String urlString)
   throws IOException {
  URL url = new URL(urlString);
  URLConnection connection = url.openConnection();
  connection.setConnectTimeout(25000);
  connection.setReadTimeout(90000);
  return connection.getInputStream();
 }

 /**
  * 從輸入資料流儲存圖片到檔案系統
  *
  * @param fileName
  * @param input
  * @return
  */
 private File saveImage(InputStream input, String fileName) {
  if (fileName.trim().isEmpty() || input == null) {
   return null;
  }
  File file = new File(fileName);
  OutputStream output = null;
  try {
   file.getParentFile().mkdirs();
   if (file.exists() && file.isFile()) {
    file.delete();
   }
   if (!file.createNewFile()) {
    return null;
   }
   output = new FileOutputStream(file);
   byte[] buffer = new byte[4 * 1024];
   do {
    // 迴圈讀取
    int numread = input.read(buffer);
    if (numread == -1) {
     break;
    }
    output.write(buffer, 0, numread);
   } while (true);
   output.flush();
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   try {
    output.close();
   } catch (IOException e) {
    e.printStackTrace();
   } catch (Exception e2) {
    e2.printStackTrace();
   }
  }
  return file;
 }
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.