一、网络加载技术
想要快速的实现网络加载,可以从2各方面入手,一个是与Server端的通讯协议;第二个就是提高自身加载速度。
首先,与Server端的通讯协议,可以采用分段加载的方式,就是在加载过程中,分为两个阶段,一个是加载整体数据的阶段,另一个是加载具体资源阶段。我们在浏览网页时经常就是通过这种方式提高访问速度,提升访问体验的。具体 就是首先获取整个页面的文字内容,获取各个图片资源的大小信息,进行页面的布局排版。之后根据具体浏览的位置,再单独发送请求,获取具体的图片资源,从而实现页面的快速显示,同时节省网络流量。为了实现这种访问方式,在客户端通过Bitmap加载网络图片时,可以通过2段访问的方式,及先获取Bitmap大小,需要时再去获取真正资源,从而大大提升页面加载速度。
private BitmapFactory.Options mOption;
mOption = new BitmapFactory.Options();
mOption.inSampleSize = 1;
//只进行大小判断
mOption.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new URL(imageUrl).openStream(),null,mOption);
if(mOption.outHeight > 210){
mOption.inSampleSize = 4;
}
mOption.inJustDecodeBounds = false;
Bitmap drawable = BitmapFactory.decodeStream(new URL(imageUrl)
.openStream(),null,mOption);
其次,就是客户端在访问Server端时,采用多线程访问的技术,同步发起资源请求,可以大大提高资源访问及申请的速度。这里比较常用的手段是采用线程池来管理资源的请求与管理。线程池拥有自己的执行队列,自动将执行请求进行队列缓存,按顺序执行请求。线程池可以有效避免手动创建线程的线程开销,线程池自动维护执行线程,在有执行请求时,不会销毁执行线程。
private ExecutorService executorService;
executorService = new ThreadPoolExecutor(CORE_THREAD_SIZE, MAX_THREAD_SIZE, 120, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardOldestPolicy());
executorService.submit(new Runnable() {public void run() {}
}
二、网络图片资源加载及内存管理
在进行客户端开发时,经常要面对的就是网络加载大量的图片,而每一张图片又是即时加载,需要手动释放资源,否则在加载新图片时经常出现OOM(Out of Memory)问题。同时为了界面显示浏览的流畅性,又需要在一定程度上、内存允许范围内的缓存请求。如何在平衡这两方面的问题,避免出现OOM,提高APP的稳定性那。这里提两个简单有效、实用的方式。
首先,根据具体的资源大小分别进行管理,这是在缓存、加载中需要处理的第一个问题,需要根据具体的需求,哪些资源对缓存的需求更强烈,那些资源对释放更迫切。使用不同的资源访问、管理方式。
接下来就根据资源的简单分类分别进行访问、管理;对于释放要求更迫切的资源来说,我们可以采用二级缓存、同步释放的方式。简单来说就是在访问网络资源获取后,复制到内部固定缓存空间,同步释放网络加载资源。
private static Bitmap mBigBitmap[] = new Bitmap[HorizontalViewer.MAX_PREVIEW_PICS];
static{
for(int i=0;i<HorizontalViewer.MAX_PREVIEW_PICS;i++){
// mDrawBitmap[i] = Bitmap.createBitmap(IMAGE_WIDTH, IMAGE_HEIGHT, Config.ARGB_8888);
mBigBitmap[i] = Bitmap.createBitmap(BIG_IMAGE_WIDTH, BIG_IMAGE_HEIGHT, Config.ARGB_8888);
}
}
Bitmap drawable = BitmapFactory.decodeStream(new URL(imageUrl)
.openStream(),null,mOption);
mCanvas = new Canvas(mBigBitmap[inx]);
mCanvas.drawBitmapdrawable new Rect(0,0,imageDrawable.getWidth(),imageDrawable.getHeight()),
new Rect(0,0,BIG_IMAGE_WIDTH,BIG_IMAGE_HEIGHT), null);
if (!drawable.isRecycled()) {
drawable.recycle();
}
通过Canvas实现对图片资源的快速复制,由于在复制过程中,Bitmap底层直接采用内存拷贝的方式进行,在效率上非常高,通过固定使用static的Bitmap缓冲池,使资源占用在一个定值内,网络异步加载的资源,在拷贝完后,迅速释放,避免内存的过高占用。
而对于缓存需求更强烈的资源来说,在访问过程中,可以采用弱引用的方式,进行加载与管理,在系统资源满足要求的情况下,系统不会释放弱引用所指向的资源,在资源紧张下,自动回收若引用资源。这样刚好满足我们对资源缓存的要求。
public Map<String, WeakReference<Bitmap>> imageCache = new HashMap<String, WeakReference<Bitmap>>();
public Bitmap loadSmallDrawable(final String imageUrl, final ImageCallback callback) {
/* 方案 :小图片的缓冲比较多 */
if (imageCache.containsKey(imageUrl)) {
WeakReference<Bitmap> softReference = imageCache.get(imageUrl);
if (softReference.get() != null) {
if (callback != null) {
callback.imageLoaded(softReference.get());
}
return softReference.get();
}
}
if (callback == null)
return null;
// 缓存中没有图像,则从网络上取出数据,并将取出的数据缓存到内存中
executorService.submit(new Runnable() {
public void run() {
try {
Bitmap drawable = BitmapFactory.decodeStream(new URL(imageUrl)
.openStream(),null,mOption);
drawable = Bitmap.createScaledBitmap(drawable, 120, 200, true);
// drawable.recycle();
imageCache.put(imageUrl, new
WeakReference<Bitmap>(drawable));
Log.e(TAG, "get a drawable");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
return null;
}
通过以上技术基本可以满足Android客户端访问网络加载资源的需求,最后一点需要注意的就是对资源的访问,尽量做到提前预知资源大小,尽量避免对图片的资源的二次加工。简单来说就是对网络加载的资源,尽量减少在内部的缩放、Alpha等的重新改变,主要由于对Bitmap的各种改变,系统都是重新创建资源,这样就导致内存空间的浪费,及比较高的时间代价。在访问资源时,通过改变采样率等方式,有效避免这种情况的发生。
private BitmapFactory.Options mOption;
mOption = new BitmapFactory.Options();
mOption.inSampleSize = 1;
//只进行大小判断
mOption.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new URL(imageUrl)
.openStream(),null,mOption);
if(mOption.outHeight > 210){
mOption.inSampleSize = 4;
}
mOption.inJustDecodeBounds = false;
Bitmap drawable = BitmapFactory.decodeStream(new URL(imageUrl)
.openStream(),null,mOption);
——欢迎转载,请注明出处http://blog.csdn.net/zyplus——