1. 程式人生 > >Android使用非同步下載快取圖片

Android使用非同步下載快取圖片

PicUtil.java

package com.example.updateUtil;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
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 android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;

public class PicUtil {
	private static final String TAG = "PicUtil";

	/**
	 * 根據一個網路連線(URL)獲取bitmapDrawable影象
	 * 
	 * @param imageUri
	 * @return
	 */
	public static BitmapDrawable getfriendicon(URL imageUri) {

		BitmapDrawable icon = null;
		try {
			HttpURLConnection hp = (HttpURLConnection) imageUri
					.openConnection();
			icon = new BitmapDrawable(hp.getInputStream());// 將輸入流轉換成bitmap
			hp.disconnect();// 關閉連線
		} catch (Exception e) {
		}
		return icon;
	}

	/**
	 * 根據一個網路連線(String)獲取bitmapDrawable影象
	 * 
	 * @param imageUri
	 * @return
	 */
	public static BitmapDrawable getcontentPic(String imageUri) {
		URL imgUrl = null;
		try {
			imgUrl = new URL(imageUri);
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		}
		BitmapDrawable icon = null;
		try {
			HttpURLConnection hp = (HttpURLConnection) imgUrl.openConnection();
			icon = new BitmapDrawable(hp.getInputStream());// 將輸入流轉換成bitmap
			hp.disconnect();// 關閉連線
		} catch (Exception e) {
		}
		return icon;
	}

	/**
	 * 根據一個網路連線(URL)獲取bitmap影象
	 * 
	 * @param imageUri
	 * @return
	 */
	public static Bitmap getusericon(URL imageUri) {
		// 顯示網路上的圖片
		URL myFileUrl = imageUri;
		Bitmap bitmap = null;
		try {
			HttpURLConnection conn = (HttpURLConnection) myFileUrl
					.openConnection();
			conn.setDoInput(true);
			conn.connect();
			InputStream is = conn.getInputStream();
			bitmap = BitmapFactory.decodeStream(is);
			is.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return bitmap;
	}

	/**
	 * 根據一個網路連線(String)獲取bitmap影象
	 * 
	 * @param imageUri
	 * @return
	 * @throws MalformedURLException
	 */
	public static Bitmap getbitmap(String imageUri) {
		// 顯示網路上的圖片
		Bitmap bitmap = null;
		try {
			URL myFileUrl = new URL(imageUri);
			HttpURLConnection conn = (HttpURLConnection) myFileUrl
					.openConnection();
			conn.setDoInput(true);
			conn.connect();
			InputStream is = conn.getInputStream();
			bitmap = BitmapFactory.decodeStream(is);
			is.close();

			Log.i(TAG, "image download finished." + imageUri);
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
		return bitmap;
	}

	/**
	 * 下載圖片 同時寫道本地快取檔案中
	 * 
	 * @param context
	 * @param imageUri
	 * @return
	 * @throws MalformedURLException
	 */
	public static Bitmap getbitmapAndwrite(String imageUri,Context context) {
		Bitmap bitmap = null;
		try {
			// 顯示網路上的圖片
			URL myFileUrl = new URL(imageUri);
			HttpURLConnection conn = (HttpURLConnection) myFileUrl
					.openConnection();
			conn.setDoInput(true);
			conn.connect();

			InputStream is = conn.getInputStream();
			File cacheFile = FileUtil.getCacheFile(imageUri,context);
			BufferedOutputStream bos = null;
			bos = new BufferedOutputStream(new FileOutputStream(cacheFile));
			Log.i(TAG, "write file to " + cacheFile.getCanonicalPath());

			byte[] buf = new byte[1024];
			int len = 0;
			// 將網路上的圖片儲存到本地
			while ((len = is.read(buf)) > 0) {
				bos.write(buf, 0, len);
			}

			is.close();
			bos.close();

			// 從本地載入圖片
			bitmap = BitmapFactory.decodeFile(cacheFile.getCanonicalPath());
//			String name = MD5Util.MD5(imageUri);

		} catch (IOException e) {
			e.printStackTrace();
		}
		return bitmap;
	}

	public static boolean downpic(String picName, Bitmap bitmap) {
		boolean nowbol = false;
		try {
			File saveFile = new File("/mnt/sdcard/download/weibopic/" + picName
					+ ".png");
			if (!saveFile.exists()) {
				saveFile.createNewFile();
			}
			FileOutputStream saveFileOutputStream;
			saveFileOutputStream = new FileOutputStream(saveFile);
			nowbol = bitmap.compress(Bitmap.CompressFormat.PNG, 100,
					saveFileOutputStream);
			saveFileOutputStream.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return nowbol;
	}

	public static void writeTofiles(Context context, Bitmap bitmap,
			String filename) {
		BufferedOutputStream outputStream = null;
		try {
			outputStream = new BufferedOutputStream(context.openFileOutput(
					filename, Context.MODE_PRIVATE));
			bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 將檔案寫入快取系統中
	 * 
	 * @param filename
	 * @param is
	 * @return
	 */
	public static String writefile(Context context, String filename,
			InputStream is) {
		BufferedInputStream inputStream = null;
		BufferedOutputStream outputStream = null;
		try {
			inputStream = new BufferedInputStream(is);
			outputStream = new BufferedOutputStream(context.openFileOutput(
					filename, Context.MODE_PRIVATE));
			byte[] buffer = new byte[1024];
			int length;
			while ((length = inputStream.read(buffer)) != -1) {
				outputStream.write(buffer, 0, length);
			}
		} catch (Exception e) {
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (outputStream != null) {
				try {
					outputStream.flush();
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return context.getFilesDir() + "/" + filename + ".jpg";
	}

	// 放大縮小圖片
	public static Bitmap zoomBitmap(Bitmap bitmap, int w, int h) {
		int width = bitmap.getWidth();
		int height = bitmap.getHeight();
		Matrix matrix = new Matrix();
		float scaleWidht = ((float) w / width);
		float scaleHeight = ((float) h / height);
		matrix.postScale(scaleWidht, scaleHeight);
		Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, width, height,
				matrix, true);
		return newbmp;
	}

	// 將Drawable轉化為Bitmap
	public static Bitmap drawableToBitmap(Drawable drawable) {
		int width = drawable.getIntrinsicWidth();
		int height = drawable.getIntrinsicHeight();
		Bitmap bitmap = Bitmap.createBitmap(width, height, drawable
				.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
				: Bitmap.Config.RGB_565);
		Canvas canvas = new Canvas(bitmap);
		drawable.setBounds(0, 0, width, height);
		drawable.draw(canvas);
		return bitmap;

	}

	// 獲得圓角圖片的方法
	public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {
		if(bitmap == null){
			return null;
		}
		
		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
				bitmap.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);

		final int color = 0xff424242;
		final Paint paint = new Paint();
		final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
		final RectF rectF = new RectF(rect);

		paint.setAntiAlias(true);
		canvas.drawARGB(0, 0, 0, 0);
		paint.setColor(color);
		canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rect, rect, paint);
		return output;
	}

	// 獲得帶倒影的圖片方法
	public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap) {
		final int reflectionGap = 4;
		int width = bitmap.getWidth();
		int height = bitmap.getHeight();

		Matrix matrix = new Matrix();
		matrix.preScale(1, -1);

		Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, height / 2,
				width, height / 2, matrix, false);

		Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
				(height + height / 2), Config.ARGB_8888);

		Canvas canvas = new Canvas(bitmapWithReflection);
		canvas.drawBitmap(bitmap, 0, 0, null);
		Paint deafalutPaint = new Paint();
		canvas.drawRect(0, height, width, height + reflectionGap, deafalutPaint);

		canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);

		Paint paint = new Paint();
		LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0,
				bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff,
				0x00ffffff, TileMode.CLAMP);
		paint.setShader(shader);
		// Set the Transfer mode to be porter duff and destination in
		paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
		// Draw a rectangle using the paint with our linear gradient
		canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
				+ reflectionGap, paint);

		return bitmapWithReflection;
	}

}


FileUtil.java


package com.example.updateUtil;


import java.io.File;
import java.io.IOException;

import android.content.Context;
import android.os.Environment;
import android.util.Log;


public class FileUtil {
	private static final String TAG = "FileUtil";

	public static File getCacheFile(String imageUri,Context context){
		File cacheFile = null;
		try {
  			 if (Environment.getExternalStorageState().equals(
    						 Environment.MEDIA_MOUNTED)) {
//   			 File sdCardDir = Environment.getExternalStorageDirectory();
				String fileName = getFileName(imageUri);
				File dir = new File(context.getFilesDir()
						+ AsynImageLoader.CACHE_DIR);////
				if (!dir.exists()) {
					dir.mkdirs();
				}
//				cacheFile = new File(sdCardDir, fileName);
				cacheFile = new File(dir, fileName);
				Log.i(TAG, "exists:" + cacheFile.exists() + ",dir:" + dir + ",file:" + fileName);
			}
		} catch (Exception e) {
			e.printStackTrace();
			Log.e(TAG, "getCacheFileError:" + e.getMessage());
		}
		
		return cacheFile;
	}
	
	public static String getFileName(String path) {
		int index = path.lastIndexOf("/");
		return path.substring(index + 1);
	}
}



AsynImageLoader.java


package com.example.mytest;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;


public class AsynImageLoader {
	private static final String TAG = "AsynImageLoader";
	// 快取下載過的圖片的Map
	private Map<String, SoftReference<Bitmap>> caches;
	// 任務佇列
	private List<Task> taskQueue;
	private boolean isRunning = false;
	static String CACHE_DIR = "/image";//////
	Context context;
	
	public AsynImageLoader(Context context){
		this.context = context;
		// 初始化變數
		caches = new HashMap<String, SoftReference<Bitmap>>();
		taskQueue = new ArrayList<AsynImageLoader.Task>();
		// 啟動圖片下載執行緒
		isRunning = true;
		new Thread(runnable).start();
	}
	
	/**
	 * 
	 * @param imageView 需要延遲載入圖片的物件
	 * @param url 圖片的URL地址
	 * @param resId 圖片載入過程中顯示的圖片資源
	 */
	public void showImageAsyn(ImageView imageView, String url, int resId){
		imageView.setTag(url);
		Bitmap bitmap = loadImageAsyn(url, getImageCallback(imageView, resId));
		
		if(bitmap == null){
			imageView.setImageResource(resId);
		}else{
			imageView.setImageBitmap(bitmap);
		}
	}
	
	public Bitmap loadImageAsyn(String path, ImageCallback callback){
		// 判斷快取中是否已經存在該圖片
		String fileName = path.substring(path.lastIndexOf("/")+1);
//		Bitmap bitmap = getBitmap(fileName);
		Log.i(TAG, "-------fileName-------:" + fileName);
//		Log.i(TAG, "-------bitmap-------:" + bitmap);
		if(caches.containsKey(path)){
			// 取出軟引用
			SoftReference<Bitmap> rf = caches.get(path);
			// 通過軟引用,獲取圖片
			Bitmap bitmap = rf.get();
			// 如果該圖片已經被釋放,則將該path對應的鍵從Map中移除掉
			if(bitmap == null){
				caches.remove(path);
			}else{
				// 如果圖片未被釋放,直接返回該圖片
				Log.i(TAG, "return image in cache" + path);
				return bitmap;
			}
		}else{
			// 如果快取中不常在該圖片,則建立圖片下載任務
			Task task = new Task();
			task.path = path;
			task.callback = callback;
			Log.i(TAG, "new Task ," + path);
			if(!taskQueue.contains(task)){
				taskQueue.add(task);
				// 喚醒任務下載佇列
				synchronized (runnable) {
					runnable.notify();
				}
			}
		}
		
		// 快取中沒有圖片則返回null
		return null;
	}
	
	public Bitmap getBitmap(String imageName){
		try {
			File dir = new File(context.getApplicationContext().getFilesDir()
					.getAbsolutePath()+CACHE_DIR+"/"+imageName);////
			Log.i(TAG, "------dir--------:" +dir);
			if (!dir.exists()) {
//				dir.mkdirs();
				return null;
			}else{
				FileInputStream fis = new FileInputStream(dir);
				Bitmap bitmap = BitmapFactory.decodeStream(fis);
				return bitmap;
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 
	 * @param imageView 
	 * @param resId 圖片載入完成前顯示的圖片資源ID
	 * @return
	 */
	private ImageCallback getImageCallback(final ImageView imageView, final int resId){
		return new ImageCallback() {
			
			@Override
			public void loadImage(String path, Bitmap bitmap) {
				if(path.equals(imageView.getTag().toString())){
					imageView.setImageBitmap(bitmap);
				}else{
					imageView.setImageResource(resId);
				}
			}
		};
	}
	
	private Handler handler = new Handler(){

		@Override
		public void handleMessage(Message msg) {
			// 子執行緒中返回的下載完成的任務
			Task task = (Task)msg.obj;
			// 呼叫callback物件的loadImage方法,並將圖片路徑和圖片回傳給adapter
			task.callback.loadImage(task.path, task.bitmap);
		}
		
	};
	
	private Runnable runnable = new Runnable() {
		
		@Override
		public void run() {
			while(isRunning){
				// 當佇列中還有未處理的任務時,執行下載任務
				while(taskQueue.size() > 0){
					// 獲取第一個任務,並將之從任務佇列中刪除
					Task task = taskQueue.remove(0);
					// 將下載的圖片新增到快取
					task.bitmap = PicUtil.getbitmapAndwrite(task.path,context);
					caches.put(task.path, new SoftReference<Bitmap>(task.bitmap));
					if(handler != null){
						// 建立訊息物件,並將完成的任務新增到訊息物件中
						Message msg = handler.obtainMessage();
						msg.obj = task;
						// 傳送訊息回主執行緒
						handler.sendMessage(msg);
					}
				}
				//如果佇列為空,則令執行緒等待
				synchronized (this) {
					try {
						this.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	};
	
	//回撥介面
	public interface ImageCallback{
		void loadImage(String path, Bitmap bitmap);
	}
	
	class Task{
		// 下載任務的下載路徑
		String path;
		// 下載的圖片
		Bitmap bitmap;
		// 回撥物件
		ImageCallback callback;
		
		@Override
		public boolean equals(Object o) {
			Task task = (Task)o;
			return task.path.equals(path);
		}
	}
}

應用--
asynImageLoader.showImageAsyn(imageView, url, resId);

刪除檔案
	
	/**
	 *      * 遞迴刪除檔案和資料夾      *       * @param file      *            要刪除的根目錄
	 *     
	 */
	public void DeleteFile(File file) {
		if (file.exists() == false) {
			handler.sendEmptyMessage(DELETE_FAIL);
			return;
		} else {
			if (file.isFile()) {
				file.delete();
				return;
			}
			if (file.isDirectory()) {
				File[] childFile = file.listFiles();
				if (childFile == null || childFile.length == 0) {
					file.delete();
					return;
				}
				for (File f : childFile) {
					DeleteFile(f);
				}
				file.delete();
			}
		}
	}
	// 儲存檔案內容
	private void writeFiles(String content) {
		try {
			// 開啟檔案獲取輸出流,檔案不存在則自動建立
			FileOutputStream fos = context.openFileOutput(FILENAME,
					Context.MODE_PRIVATE);
			fos.write(content.getBytes("UTF-8"));
			fos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// 讀取檔案內容
		private String readFiles() {
			String content = null;
			try {
				FileInputStream fis = context.openFileInput(FILENAME);
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				byte[] buffer = new byte[1024];
				int len = 0;
				while ((len = fis.read(buffer)) != -1) {
					baos.write(buffer, 0, len);
				}
				content = baos.toString();
				fis.close();
				baos.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			return content;
		}