`
刘亚鑫
  • 浏览: 18221 次
社区版块
存档分类
最新评论

异步下载图片+图片缓存

 
阅读更多

代码参考自:jamendo,有一定修改。

 

 

功能如下:


 

流程如下:



 

 

 

 

 

 

 

   RemoteImageViewActivity:

 

public class RemoteImageViewActivity extends Activity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		RemoteImageView img = (RemoteImageView) findViewById(R.id.remote_img);
		img.setDefaultImage(R.drawable.ic_launcher);
		img.setImageUrl("http://img2.kwcdn.kuwo.cn:81/star/albumcover/120/7/8/83787_1323997225.jpg");
	}

	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
	}
}

 

 

  ImageCache:

 

public class ImageCache extends WeakHashMap<String, Bitmap>{

	/**
	 * 判断该url是否存在
	 * @param url
	 * @return
	 */
	public boolean isCached(String url){
		return containsKey(url) && get(url) != null;
	}
}

 

 

   RemoteImageApplication:

  

public class RemoteImageApplication extends Application {

	public static final String TAG = "RemoteImageApplication";

	private static RemoteImageApplication application;

	private ImageCache mImageCache;

	public SharedPreferences prefs = null;

	
	public static RemoteImageApplication getInstance() {
		return application;
	}

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();

		application = this;

		mImageCache = new ImageCache();

		prefs = PreferenceManager.getDefaultSharedPreferences(this);
	}

	public ImageCache getImageCache() {
		return mImageCache;
	}
}

 

   

    RemoteSettings:

   

public class RemoteSettings {

	public static final String CACHE_SIZE = "cache_size";  //图片缓存保留大小,如果超过该大小,即进行自动清除缓存.

}

   

   RemoteImageView:

  

public class RemoteImageView extends ImageView {

	private Context mContext;

	private static int mCacheSize = 150; // 设置的缓存大小。

	private static final int MAX_FAILURES = 3; // 下载的尝试请求次数

	private int mFailure; // 下载失败次数

	private String mUrl; // 当前下载的url

	private String mCurrentlyGrabbedUrl; // 当前下载成功的url

	private final static String JAMENDO_DIR = "Android/data/com.teleca.jamendo"; // 文件缓存存放的路径.

	private final static long MB = 1073741824;

	public RemoteImageView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		mContext = context;
	}

	public RemoteImageView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mContext = context;
	}

	public RemoteImageView(Context context) {
		super(context);
		mContext = context;
	}

	/**
	 * 设置默认图片
	 */
	public void setDefaultImage(Integer resid) {
		setImageResource(resid);
	}

	/**
	 * 设置需要异步加载的图片
	 */
	public void setImageUrl(String url) {

		// 下载失败进行重试,如果重试次数超过规定的限制,则直接返回.
		if (mUrl != null
				&& mUrl.equals(url)
				&& (mCurrentlyGrabbedUrl == null || (mCurrentlyGrabbedUrl != null && !mCurrentlyGrabbedUrl
						.equals(url)))) {
			mFailure++;
			if (mFailure > MAX_FAILURES) {
				Log.e(RemoteImageApplication.TAG, "下载该图片地址失败:" + url);
				return;
			}
		} else {

			mUrl = url;
			mFailure = 0;
		}

		ImageCache imageCache = RemoteImageApplication.getInstance()
				.getImageCache();

		if (imageCache.isCached(url)) {
			setImageBitmap(imageCache.get(url));
		} else {
			// 如果内存中没有该缓存,则从文件中进行查找.
			String fileName = convertUrlToFileName(url); // 进行文件名处理

			String filepath = getDirectory(fileName); // 取得缓存文件夹目录

			String pathFileName = filepath + "/" + fileName; // 组拼文件

			File pathFile = new File(pathFileName);
			if (!pathFile.exists()) {
				try {
					pathFile.createNewFile();
				} catch (IOException e) {
					Log.d(RemoteImageApplication.TAG, "创建图片文件失败:"
							+ pathFileName);
				}
			}

			Bitmap tbmp = BitmapFactory.decodeFile(pathFileName);

			if (tbmp == null) {
				Log.d(RemoteImageApplication.TAG, "图片文件不存在,开始进行下载");
				try {
					new DownloadTask().execute(url);
				} catch (RejectedExecutionException e) {
					Log.d(RemoteImageApplication.TAG, "下载失败");
				}
			} else {
				Log.i(RemoteImageApplication.TAG, "从文件中加载图片");
				RemoteImageApplication.getInstance().getImageCache()
						.put(url, tbmp);
				this.setImageBitmap(tbmp);
			}

			updateCacheSize(pathFileName); // 进行检测文件大小,以便于清除缓存.

		}

	}

	private void updateCacheSize(String pathFileName) {
		// TODO Auto-generated method stub
		updateSizeCache(pathFileName);

	}

	/**
	 * 检查文件目录是否超过规定的缓存大小
	 * 
	 * @param fileName
	 */
	private void updateSizeCache(String pathFileName) {
		// TODO Auto-generated method stub
		mCacheSize = PreferenceManager.getDefaultSharedPreferences(mContext)
				.getInt(RemoteSettings.CACHE_SIZE, 100); // 读取设置的缓存大小,前台可以动态设置此值

		if (isSDCardEnable()) {
			String extStorageDirectory = Environment
					.getExternalStorageDirectory().toString(); // 取得SD根路径

			String dirPath = extStorageDirectory + "/" + JAMENDO_DIR
					+ "/imagecache";

			File dirFile = new File(dirPath);

			File[] files = dirFile.listFiles();

			long dirSize = 0;

			for (File file : files) {

				dirSize += file.length();
			}

			if (dirSize > mCacheSize * MB) {
				clearCache();
			}
		}

	}

	/**
	 * 异步下载图片
	 * 
	 * @ClassName: DownloadTask
	 * @author 姜涛
	 * @version 1.0 2012-1-15 下午5:06:21
	 */
	class DownloadTask extends AsyncTask<String, Void, String> {

		private String mTaskUrl;
		private Bitmap mBmp = null;

		@Override
		public void onPreExecute() {
			// loadDefaultImage();
			super.onPreExecute();
		}

		@Override
		public String doInBackground(String... params) {

			mTaskUrl = params[0];
			InputStream stream = null;
			URL imageUrl;
			Bitmap bmp = null;

			try {
				imageUrl = new URL(mTaskUrl);
				try {
					stream = imageUrl.openStream();
					bmp = BitmapFactory.decodeStream(stream);
					try {
						if (bmp != null) {
							mBmp = bmp;
							RemoteImageApplication.getInstance()
									.getImageCache().put(mTaskUrl, bmp);
							Log.d(RemoteImageApplication.TAG,
									"图片缓存到application中: " + mTaskUrl);

						}
					} catch (NullPointerException e) {
						Log.w(RemoteImageApplication.TAG, "下载失败,图片为空:"
								+ mTaskUrl);
					}
				} catch (IOException e) {
					Log.w(RemoteImageApplication.TAG, "无法加载该url:" + mTaskUrl);
				} finally {
					try {
						if (stream != null) {
							stream.close();
						}
					} catch (IOException e) {
					}
				}

			} catch (MalformedURLException e) {
				e.printStackTrace();
			}
			return mTaskUrl;
		}

		@Override
		public void onPostExecute(String url) {
			super.onPostExecute(url);

			Bitmap bmp = RemoteImageApplication.getInstance().getImageCache()
					.get(url);
			if (bmp == null) {
				Log.w(RemoteImageApplication.TAG, "尝试重新下载:" + url);
				RemoteImageView.this.setImageUrl(url);
			} else {

				RemoteImageView.this.setImageBitmap(bmp);
				mCurrentlyGrabbedUrl = url;
				saveBmpToSd(mBmp, url);

			}
		}

	};

	/**
	 * 把图片保存到本地
	 * 
	 * @param bm
	 * @param url
	 */
	private void saveBmpToSd(Bitmap bm, String url) {

		if (bm == null) {
			return;
		}

		if (mCacheSize == 0) {
			return;
		}

		String filename = convertUrlToFileName(url);
		String dir = getDirectory(filename);
		File file = new File(dir + "/" + filename);

		try {
			file.createNewFile();
			OutputStream outStream = new FileOutputStream(file);
			bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
			outStream.flush();
			outStream.close();

			Log.i(RemoteImageApplication.TAG, "图片已保存到sd卡");

		} catch (FileNotFoundException e) {
			Log.w(RemoteImageApplication.TAG, "无法找到文件目录");

		} catch (IOException e) {
			Log.w(RemoteImageApplication.TAG, "操作文件出错");
		}

	}

	/**
	 * 组拼文件名,后缀名用dat代替,避免别人使用图片管理器搜索出这种对于她们无用的图片.
	 * 
	 * @param url
	 * @return
	 */
	private String convertUrlToFileName(String url) {
		String filename = url;
		filename = filename.replace("http://", "");
		filename = filename.replace("/", ".");
		filename = filename.replace(":", ".");
		filename = filename.replace("jpg", "dat");
		filename = filename.replace("png", "dat");
		return filename;
	}

	/**
	 * 返回缓存图片所存放的文件夹
	 * 
	 * @param filename
	 * @return
	 */
	private String getDirectory(String filename) {

		String extStorageDirectory = Environment.getExternalStorageDirectory()
				.toString(); // 取得SD根路径

		String dirPath = extStorageDirectory + "/" + JAMENDO_DIR
				+ "/imagecache";

		File dirFile = new File(dirPath);

		if (!dirFile.exists()) {
			dirFile.mkdirs();
		}

		return dirPath;

	}

	/**
	 * 清除缓存
	 */
	private void clearCache() {

		if (isSDCardEnable()) {
			String extStorageDirectory = Environment
					.getExternalStorageDirectory().toString(); // 取得SD根路径

			String dirPath = extStorageDirectory + "/" + JAMENDO_DIR
					+ "/imagecache";

			File dir = new File(dirPath);

			File[] files = dir.listFiles(); // 取得该目录下的所有文件

			if (files == null || files.length == 0) {
				return;
			}

			for (File file : files) {
				file.delete();
			}

			Log.d(RemoteImageApplication.TAG, "已清除缓存:" + dirPath);
		}
	}

	/**
	 * 判断SD卡是否可用
	 */
	public static boolean isSDCardEnable() {

		return Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED);
	}

}

 

   

 


 代码参见附件.

 

 

 

  • 大小: 18.5 KB
  • 大小: 36.9 KB
分享到:
评论
1 楼 jyh149129 2013-03-01  
我android新手,能否给我个ViewFlipper 调用的例子,需要5个网络图片,谢谢jyh149129@126.com

相关推荐

Global site tag (gtag.js) - Google Analytics