- 在某些时候我们需要在Android设备上下载远端服务器上的图片来进行显示,这里我整理出两种比较好的方法来实现远程图片的下载。
- 方法一、直接通过Android官方提供的Http类访来问远程服务器,这里AndroidHttpClient是SDK2.2中新出的方法,APILevel为8,大家需要注意下,静态访问可以直接调用,如果SDK版本较低可以考虑Apache的Http库,当然HttpURLConnection或URLConnection也可以。
- staticBitmapdownloadBitmap(Stringurl){
- finalAndroidHttpClientclient=AndroidHttpClient.newInstance("linux初学三月");
- finalHttpGetgetRequest=newHttpGet(url);
- try{
- HttpResponseresponse=client.execute(getRequest);
- finalintstatusCode=response.getStatusLine().getStatusCode();
- if(statusCode!=HttpStatus.SC_OK){
- Log.e("cwjDebug","Error"+statusCode+"whileretrievingbitmapfrom"+url);
- returnnull;
- }
- finalHttpEntityentity=response.getEntity();
- if(entity!=null){
- InputStreaminputStream=null;
- try{
- inputStream=entity.getContent();
- finalBitmapbitmap=BitmapFactory.decodeStream(inputStream);
- returnbitmap;
- }finally{
- if(inputStream!=null){
- inputStream.close();
- }
- entity.consumeContent();
- }
- }
- }catch(Exceptione){
- getRequest.abort();
- Log.e("Debug","Errorwhileretrievingbitmapfrom"+url,e.toString());
- }finally{
- if(client!=null){
- client.close();
- }
- }
- returnnull;
- }
- 复制代码
- 这里提醒大家,BitmapFactory类的decodeStream方法在网络超时或较慢的时候无法获取完整的数据,这里我们通过继承FilterInputStream类的skip方法来强制实现flush流中的数据,主要原理就是检查是否到文件末端,告诉http类是否继续。
- //这个方法没有使用到
- staticclassFlushedInputStreamextendsFilterInputStream{
- publicFlushedInputStream(InputStreaminputStream){
- super(inputStream);
- }
- @Override
- publiclongskip(longn)throwsIOException{
- longtotalBytesSkipped=0L;
- while(totalBytesSkipped<n){
- longbytesSkipped=in.skip(n-totalBytesSkipped);
- if(bytesSkipped==0L){
- intbyte=read();
- if(byte<0){
- break;//wereachedEOF
- }else{
- bytesSkipped=1;//wereadonebyte
- }
- }
- totalBytesSkipped+=bytesSkipped;
- }
- returntotalBytesSkipped;
- }
- }
- 复制代码
- 方法二、通过AsyncTask的异步任务
- 从Android1.5固件开发平台开始Google提供了一个AsyncTask类来帮助开发者处理异步下载的实现,相对于Thread线程而言他可以运行在UI线程中,其内部的实现是从Java5开始的并发包concurrent中派生而来的,总体实现比较可靠就是资源占用略大了些。不过使用起来比简单。这里下载图片类ImageDownloader类的download方法可以很好的处理实现UI显示等操作,参数一url为远程server上文件的url,第二个参数为imageview对象,可以直接让imageview显示出下载的远程图片。
- publicclassImageDownloader{
- publicvoiddownload(Stringurl,ImageViewimageView){
- BitmapDownloaderTasktask=newBitmapDownloaderTask(imageView);
- task.execute(url);
- }
- }
- }
- 复制代码
- 有关具体的AsyncTask类实现,考虑到图片可能较大,为了给JVM充分的空间存储,这里推荐大家使用弱引用来保存ImageView对象。
- classBitmapDownloaderTaskextendsAsyncTask<String,Void,Bitmap>{
- privateStringurl;
- privatefinalWeakReference<ImageView>imageViewReference;//使用WeakReference解决内存问题
- publicBitmapDownloaderTask(ImageViewimageView){
- imageViewReference=newWeakReference<ImageView>(imageView);
- }
- @Override
- protectedBitmapdoInBackground(String...params){//实际的下载线程,内部其实是concurrent线程,所以不会阻塞
- returndownloadBitmap(params[0]); //这方法在前面方法一中
- }
- @Override
- protectedvoidonPostExecute(Bitmapbitmap){//下载完后执行的
- if(isCancelled()){
- bitmap=null;
- }
- if(imageViewReference!=null){
- ImageViewimageView=imageViewReference.get();
- if(imageView!=null){
- imageView.setImageBitmap(bitmap);//下载完设置imageview为刚才下载的bitmap对象
- }
- }
- }
- }