最近在开发云相册,似乎只要和云挂钩貌似都好像很牛逼一样,其实做客户端是很简单的,只需要将图片从云端下载下来就好。我还没进公司时,公司就用了个最简单的方法,当浏览某张图片时才开始下载当前图片,而且图片存放进bitmap中并没有存放于本地,所以当用户再次浏览此图片时会再次执行下载操作,我一用就觉得蛋疼了,然后果断提出修改此功能,于是,于是就有了我的“四线程图片下载”。
先简单介绍下,四大线程名为:ImageControlAsyncTask,ImageAsyncTask,ImageSingleAsyncTask,ImageListenerAsyncTask。ImageControlAsyncTask线程负责控制进入缩略图显示界面就一张一张开始下载图片(注意:是一张一张哦);ImageAsyncTask线程负责一张一张图片的显示;ImageSingleAsyncTask线程负责当用户点击某一张图片,但控制线程还没走到此处时,另开一线程对此图片进行下载,不需要等待;ImageListenerAsyncTask线程负责当存在一个线程正在下载当前浏览图片,却没有下载完成时的处理,它不执行任何下载操作,仅仅是等待下载完成那一刻及时进行更新当前图片。如此一介绍,估计我的线程架构就已经很清晰了,下面慢慢介绍代码部分。
相信做过图片浏览的人都应该熟悉ViewFlipper,没错我们相册也是用的这种浏览方法,并且将加载图片的所有代码都放进了LoadBitmap方法中,下面是LoadBitmap方法:
说到Flipper就不得不说它的一个BUG,不管点击的是哪张图片当屏幕翻转时都会显示这张图片,中间不管你手指滑动了几张图,但是这个不是本文的重点,下一篇我会和大家一起探讨下这个问题。(不行,还是先写这个吧,本文太长了,估计要写几天)
[代码]java代码:
private void LoadBitmap() {
positionstatic = position;//设置静态变量供线程判别用户是否浏览当前图片调用
CloudGridView.fixedposition = true;//设置状态为已点击进入
//System.out.println("有第二次调用"+position+ ":---" + HiCloudAlbum.ThumPathFlag[position]);
try {
Log.i(TAG, "!!!!"+cloudImageList.get(position).getOriginalPath());
//打开云相册即开始下载,线程调用by zero
String originalPath = cloudImageList.get(position).getOriginalPath();
realLocalPath = SYSPath.ImgCachePATH + "/" + originalPath.substring(originalPath.lastIndexOf("/") + 1);
System.out.println("本地路径:" + realLocalPath);
//System.out.println("真实地址测试"+realLocalPath + "根据另一地址:" + SYSPath.ImgCachePATH + "/" + originalPath.substring(originalPath.lastIndexOf("/") + 1));
//寻找ID
for(int i = 0;i < CloudGridView.imagecacheentity.size();i++){
if(cloudImageList.get(position).getObjectId().equals(CloudGridView.imagecacheentity.get(i).getObjectID())){
localID = CloudGridView.imagecacheentity.get(i).getID();
break;
}
}
if(!(new File(realLocalPath)).exists()){
//bitmap = bitmapTool.getBitmapByUrl(cloudImageList.get(position).getOriginalPath(),this.screenWidth, this.screenHeight, cloudImageList.get(position).getObjectId());
//图片临时文件夹中不存在时,另开线程下载,下载完毕如果用户还在浏览此图片则刷新
System.out.println("图片不存在,需要重头下载");
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fipper_loading);
this.setWiteImage(bitmap);
ImageSingleAsyncTask asyncTask = new ImageSingleAsyncTask (position,cloudImageList.get(position).getObjectId(),this,originalPath,localID);
asyncTask.execute();
return;
}else if(CloudGridView.imagecacheentity.get(localID).isDownFlag() == true){
//已经下载完毕时
System.out.println("已经下载完毕,直接调用");
//by LLH
//bitmap = ImageSetion.getThumbnails(1000, 1500, realLocalPath, bitmap);
try {
if(bitmap != null)
{
if(!bitmap.isRecycled())
{
Log.i(TAG, "last bitmap is NOT recycle, do it now");
bitmap.recycle();
System.gc();
}
}
bitmap = new BitmapTool(this).getBitmap(realLocalPath,this.screenWidth, this.screenHeight);
} catch (FileNotFoundException e) {
Log.e(TAG, "getBitmap() Exception");
// TODO Auto-generated catch block
e.printStackTrace();
}
//end LLH
}else{
//只下载了部分时
//System.out.println("只下载了一部分等待下载完毕,启动监听");
System.out.println("只下载了一部分,需要等待线程下载");
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fipper_loading);
this.setWiteImage(bitmap);
//随时监听,如果下载完毕且用户还在浏览这张图片则刷新
ImageListenerAsyncTask asyncTask = new ImageListenerAsyncTask (position,this,cloudImageList.get(position).getObjectId(),originalPath,localID);
asyncTask.execute();
return;
}
if (bitmap == null)
{
Log.e(TAG, "bitmap is null");
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fipper_loading);
Log.e(TAG, "after decodeResource");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 得到图片加载压缩后的宽和高
if (bitmap != null)
{
Log.i(TAG, "bitmap got, get width and width");
this.bitmapWidth = bitmap.getWidth();
this.bitmapHeight = bitmap.getHeight();
pictureImageView.setImageBitmap(bitmap);
}
// 调整图片
Log.i(TAG, "adjust bitmap");
this.adjustBitmap();
}
说到Flipper就不得不说它的一个BUG,不管点击的是哪张图片当屏幕翻转时都会显示这张图片,中间不管你手指滑动了几张图,但是这个不是本文的重点,下一篇我会和大家一起探讨下这个问题。(不行,还是先写这个吧,本文太长了,估计要写几天)