zoukankan      html  css  js  c++  java
  • 关于开源项目androidImagedownloader的学习笔记

     

    关于开源项目android--Imagedownloader的学习笔记

    2011-03-24 16:44 by shy.ang, 155 visits, 收藏, 编辑

      一个开源项目,关于图像异步缓存下载的简单apps,网上有相应的代码,但是没有任何说明和讲解(英文blog中有,讲了一下框架),那就自己研究吧。

      主要对ImageDownloader分析:

      Bitmap downloadBitmap(String url);//从网站下载一幅图片,比较简单

          HttpClient

          AndroidHttpClient:Apache DefaultHttpClient的子类,已经配置好默认的合理设置和Android注册过的方案。不能直接创建对象。

                  AndroidHttpClient  newInstance(String userAgent,Context context)创建一个新HttpClient对象。

           HttpResponse:一个HTTP应答。

                HttpEntity getEntity(),获得应答的消息实例

          HttpEntity:一个可以发送接收HTTP消息的实例。

                 在一些情况下,javaDoc根据它们的内容来源把entity分三种:streamed,即内容来源是数据流,一般不可重复的;self-contained,内容来自内

                存也意味着和连接以及其他entities没有关系,一般可重复;wrapping,内容从另一个entity获得。

                InputStream  getContent():创建实例的一个新的InputStream对象 

                consumeContent():这个方法被调用意味着这个实例的内容不再被请求了,而该实例分配的所有资源都会被释放。


      但是在 BitmapFactory.decodeStream 之前版本的bug可能会阻止代码进行慢连接,而newFlushedInputStream(inputStream)方法可以解决这个问题。

      static class FlushedInputStream extends FilterInputStream;其中里面的skip函数是为了使在以后的读输入流时准确的跳过n个字节。

    static class FlushedInputStream extends FilterInputStream {
    public FlushedInputStream(InputStream inputStream) {
    super(inputStream);
    }

    @Override
    public long skip(long n) throws IOException {
    long totalBytesSkipped = 0L;
    while (totalBytesSkipped < n) {
    long bytesSkipped = in.skip(n - totalBytesSkipped);
    if (bytesSkipped == 0L) {
    int byte = read();//read()只读一个字节,但返回0~255的随机数
    if (byte < 0) {
    break; //到文件结尾
    } else {
    bytesSkipped
    = 1; // 读一个字节,这里当跳过0个字节时为什么要读一个字节不是太懂……
    }
    }
    totalBytesSkipped
    += bytesSkipped;
    }
    return totalBytesSkipped;
    }
    }


      如果在ListAdapter的getView方法中直接下载图片,效果会很卡,因为每一个新图像的显示都要等图像下载下来

      非常遗憾的是,AndroidHttpClient竟然不能在主线程里运行,否则会显示"This thread forbids HTTP requests" 错误信息。对于AsyncTask类,它提供其中一个最简单的方法来使新任务脱离UI线程运行。

      我们创建了一个ImageDownloader类来负责生成这些新的下载任务(task),它提供download方法来分配一张从URL下载的图片到对应的ImageView中。

     

    public class ImageDownloader {
    public void download(String url, ImageView imageView) {
    BitmapDownloaderTask task
    = new BitmapDownloaderTask(imageView);
    task.execute(url);
    }
    }

      BitmapDownloaderTask是AsyncTask的子类,用来实际下载图片的。调用execute(url)来运行它,能够立即返回结果,这也是UI线程调用它的主要原因。

      其中doInBackground方法中调用了downloadBitmap来下载图片,onPostExecute是当下载结束时UI线程调用的,将存储在BitmapDownloaderTask中的imageView和下载的Bitmap相关联,而这个ImageView是一个弱引用,可以被系统回收,所以要在onpostExecute中检查弱引用和这个imageView不为空。

    class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
    private String url;
    private final WeakReference<ImageView> imageViewReference;

    public BitmapDownloaderTask(ImageView imageView) {
    imageViewReference
    = new WeakReference<ImageView>(imageView);
    }

    @Override
    // Actual download method, run in the task thread
    protected Bitmap doInBackground(String... params) {
    // params comes from the execute() call: params[0] is the url.
    return downloadBitmap(params[0]);
    }
    @Override
    // Once the image is downloaded, associates it to the imageView
    protected void onPostExecute(Bitmap bitmap) {
    if (isCancelled()) {
    bitmap
    = null;
    }

    if (imageViewReference != null) {
    ImageView imageView
    = imageViewReference.get();
    if (imageView != null) {
                BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
                
    // Change bitmap only if this process is still associated with this ImageView
                
    if (this == bitmapDownloaderTask) {
                    imageView
    .setImageBitmap(bitmap);
                
    }
            }
    }
    }
    }

      对于ListView上的图像浏览,当用户快速滑动ListView时,某一个ImageView对象会被用到很多次,每一次显示都会触发一个下载,然后改变对应的图片。和大多数并行应用一样,有顺序相关的问题。在这个程序中,不能保证下载会按开始的顺序结束,有可能先开始的后下载完,“ The result is that the image finally displayed in the list may come from a previous item, which simply happened to have taken longer to download. ”  结果就是,由于与该item对应的网络图片下载慢,导致该item位置还暂时显示着之前的item显示的图片(还没被刷新,有可能长时间不被刷新

      为了解决这个问题,我们应该记住下载的顺序,使得最后的下载会被有效地显示,要让每一个ImageView记住它们的上一次下载任务。因此我们给出了DownloadedDrawable类,向ImageView中加入对对应下载任务的弱引用来暂时绑定正在下载图片的ImageView。

      static class DownloadedDrawable extends ColorDrawable ;//该类包含了一个对下载的弱引用

    static class DownloadedDrawable extends ColorDrawable {  
      private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;

    public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
    super(Color.BLACK);
    bitmapDownloaderTaskReference
    =
    new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
    }
    public BitmapDownloaderTask getBitmapDownloaderTask() {
    return bitmapDownloaderTaskReference.get();
       }
     }

      上面ImageDownload中的download修改为:

    public void download(String url, ImageView imageView) {
    if (cancelPotentialDownload(url, imageView)) {
    BitmapDownloaderTask task
    = new BitmapDownloaderTask(imageView);
    DownloadedDrawable downloadedDrawable
    = new DownloadedDrawable(task);
    imageView.setImageDrawable(downloadedDrawable);
    task.execute(url);
    }
    }

    private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageview);

    //通过ImageView得到对应的下载

    private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
    if (imageView != null) {
    Drawable drawable
    = imageView.getDrawable();
    if (drawable instanceof DownloadedDrawable) {
    DownloadedDrawable downloadedDrawable
    = (DownloadedDrawable)drawable;
    return downloadedDrawable.getBitmapDownloaderTask();
    }
    }
    return null;
    }

    下面总结下载过程:

        download(url , imageview)——>

              @创建一个和该imageview相对应的下载任务,这个任务对imageview进行弱引用

              @创建与这个任务相对应的DownloadedDrawable,对这个任务弱引用

              @imageview加载DownloadedDrawable

              @执行下载任务,下载对应url的图像 ——execute(url)进入下载任务类

        在下载任务类中:

            ——>doInBackground  ===>downloadBitmap(url) 下载图片,结果Bitmap作为下面的参数

            ——>onPostExcute(Bitmap)

                   @获得任务引用的imageview

                   @通过DownloadedDrawable获得该imageview所对应的任务

                   @如果当前任务是这个imageview所对应的任务,则设置这个imageview的图片为下载下

                    来的Bitmap

    imageview和任务相互弱引用,形成绑定关系

     

    引用:http://www.cnblogs.com/shyang--TechBlogs/archive/2011/03/24/1994080.html

  • 相关阅读:
    diary and html 文本颜色编辑,行距和其它编辑总汇
    bash coding to changeNames
    virtualbox ubuntu 网络连接 以及 连接 secureCRT
    linux 学习6 软件包安装
    linux 学习8 权限管理
    vim 使用2 转载 为了打开方便
    ubuntu
    linux 学习15 16 启动管理,备份和恢复
    linux 学习 14 日志管理
    linux 学习 13 系统管理
  • 原文地址:https://www.cnblogs.com/xiaoxiaoboke/p/2088280.html
Copyright © 2011-2022 走看看