如何使用AsyncTask从Url设置图像?

时间:2013-01-15 06:33:13

标签: android multithreading android-asynctask android-drawable

我是一名新手程序员,我正在制作一个Android程序,该程序在给定网址的ImageView上显示图像。我的问题是你如何在AsyncTask上使用它?

这些代码适用于min SDK 2.2,但我切换到min SDK 3.0,因此它需要在AsyncTask上运行。谢谢您的帮助! :)

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    satellite(); //satellite's image from main menu

}

//******satellite url
private void satellite() {
    // TODO Auto-generated method stub
    ImageView imgView =(ImageView)findViewById(R.id.satellite);
    Drawable drawable = LoadImageFromWeb("http://www.pagasa.dost.gov.ph/wb/sat_images/satellite.gif");
    imgView.setImageDrawable(drawable);        
}

private Drawable LoadImageFromWeb(String url){
      try{
          InputStream is = (InputStream) new URL(url).getContent();
          Drawable d = Drawable.createFromStream(is, "src name");
          return d;
      }catch (Exception e) {
          System.out.println("Exc="+e);
          return null;
      }
}

7 个答案:

答案 0 :(得分:3)

好吧,我不知道为什么android SDK不支持它(还)我通过UrlImageView类扩展了ImageView类,具有异步加载和缓存支持。我把我班上的代码放在下面,这是即插即用的。类的主体在我的帖子的末尾,现在我写了两行如何使用方便的方法。

现在支持另外两种方法:

setImageUrl(URL url) // sets the bitmap by its URL
cancelLoading();     // tell this view to cancel pending load

如何使用您的java代码:

// [somewhere in your activity]
UrlImageView urlImg = new UrlImageView(this).setImageUrl("http://abc.png");
...
urlImg.setImageUrl("http://abc2.png"); // works like expected

如何在布局中绑定:

<!-- thumbnail -->
<com.gplushub.android.view.UrlImageView
    android:id="@+id/thumbnail"
    android:layout_width="64dp"
    android:layout_height="64dp"
    android:layout_gravity="center_vertical"
    android:layout_marginRight="2dp"
    android:scaleType="fitXY" />

..再次在你的活动java代码中:

((UrlImageView)findViewById(R.id.thumbnail)).setImageUrl("http://foo.bar.png");

我在包含100多个条目的列表中使用它 - 非常好。这里是类体,你可以使用它,修改它,扩展它,无论你喜欢什么:

package com.gplushub.android.view;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;

/**
 * an {@link ImageView} supporting asynchronous loading from URL. Additional
 * APIs: {@link #setImageURL(URL)}, {@link #cancelLoading()}.
 * 
 * @author ep@gplushub.com / Eugen Plischke
 * 
 */
public class UrlImageView extends ImageView {
  private static class UrlLoadingTask extends AsyncTask<URL, Void, Bitmap> {
    private final ImageView updateView;
    private boolean         isCancelled = false;
    private InputStream     urlInputStream;

    private UrlLoadingTask(ImageView updateView) {
      this.updateView = updateView;
    }

    @Override
    protected Bitmap doInBackground(URL... params) {
      try {
        URLConnection con = params[0].openConnection();
        // can use some more params, i.e. caching directory etc
        con.setUseCaches(true);
        this.urlInputStream = con.getInputStream();
        return BitmapFactory.decodeStream(urlInputStream);
      } catch (IOException e) {
        Log.w(UrlImageView.class.getName(), "failed to load image from " + params[0], e);
        return null;
      } finally {
        if (this.urlInputStream != null) {
          try {
            this.urlInputStream.close();
          } catch (IOException e) {
            ; // swallow
          } finally {
            this.urlInputStream = null;
          }
        }
      }
    }

    @Override
    protected void onPostExecute(Bitmap result) {
      if (!this.isCancelled) {
        // hope that call is thread-safe
        this.updateView.setImageBitmap(result);
      }
    }

    /*
     * just remember that we were cancelled, no synchronization necessary
     */
    @Override
    protected void onCancelled() {
      this.isCancelled = true;
      try {
        if (this.urlInputStream != null) {
          try {
            this.urlInputStream.close();
          } catch (IOException e) {
            ;// swallow
          } finally {
            this.urlInputStream = null;
          }
        }
      } finally {
        super.onCancelled();
      }
    }
  }

  /*
   * track loading task to cancel it
   */
  private AsyncTask<URL, Void, Bitmap> currentLoadingTask;
  /*
   * just for sync
   */
  private Object                       loadingMonitor = new Object();

  public UrlImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  public UrlImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public UrlImageView(Context context) {
    super(context);
  }

  @Override
  public void setImageBitmap(Bitmap bm) {
    cancelLoading();
    super.setImageBitmap(bm);
  }

  @Override
  public void setImageDrawable(Drawable drawable) {
    cancelLoading();
    super.setImageDrawable(drawable);
  }

  @Override
  public void setImageResource(int resId) {
    cancelLoading();
    super.setImageResource(resId);
  }

  @Override
  public void setImageURI(Uri uri) {
    cancelLoading();
    super.setImageURI(uri);
  }

  /**
   * loads image from given url
   * 
   * @param url
   */
  public void setImageURL(URL url) {
    synchronized (loadingMonitor) {
      cancelLoading();
      this.currentLoadingTask = new UrlLoadingTask(this).execute(url);
    }
  }

  /**
   * cancels pending image loading
   */
  public void cancelLoading() {
    synchronized (loadingMonitor) {
      if (this.currentLoadingTask != null) {
        this.currentLoadingTask.cancel(true);
        this.currentLoadingTask = null;
      }
    }
  }
}

答案 1 :(得分:2)

如果图像不是那么大,您可以使用匿名类来执行异步任务。这就是:

ImageView mChart = (ImageView) findViewById(R.id.imageview);
String URL = "http://www...anything ...";

mChart.setTag(URL);
new DownloadImageTask.execute(mChart);

,任务类是

public class DownloadImagesTask extends AsyncTask<ImageView, Void, Bitmap> {
   ImageView imageView = null;
   @Override
   protected Bitmap doInBackground(ImageView... imageViews) {
      this.imageView = imageViews[0];
      return download_Image((String)imageView.getTag());
   }

   @Override
   protected void onPostExecute(Bitmap result) {
      imageView.setImageBitmap(result);
   }

   private Bitmap download_Image(String url) {
       ...
   }

答案 2 :(得分:1)

尝试使用此代码,将您的drawable变量设为全局变量并更改您的卫星函数,如下所示:

private void satellite() {
      // TODO Auto-generated method stub
      ImageView imgView =(ImageView)findViewById(R.id.satellite);
      new yourTask().execute();
}

然后像这样创建asyncTask类:

private class yourTask extends AsyncTask<Integer, Void, Integer> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        //show a progress bar
    }

    @Override
    protected String doInBackground(Integer... params) {
        drawable  =  LoadImageFromWeb("http://www.pagasa.dost.gov.ph/wb/sat_images/satellite.gif"); 
        return 0; 
    }      

    @Override
    protected void onPostExecute(Integer result) {
        super.onPostExecute(result);
        imgView.setImageDrawable(drawable);   
    }
}

答案 3 :(得分:0)

以下是Aynctask实现的代码 在Aynctask类中将可绘制对象设为全局。

Class MyDownloader extends AsyncTask<Void,Void,String>{

    Drawable drawable;    
    @Override
    public String doInBackground(Void... args){

        drawable = LoadImageFromWeb("http://www.pagasa.dost.gov.ph/wb/sat_images/satellite.gif");
        return null; // here you can pass any string on response as on error or on success

    }

    public void onPostExecute(String result){

        if(drawable!=null){

            imgView.setImageDrawable(drawable);

        }

    }

}

现在创建此类的对象并执行它

private void satellite() {
    // TODO Auto-generated method stub
  ImageView imgView =(ImageView)findViewById(R.id.satellite);
  new MyDownloader.execute();

}

以下是缓存图像的示例链接,请查看此链接和示例

https://github.com/novoda/ImageLoader

答案 4 :(得分:0)

您在以后进行任何网络操作时都是对的Android 2.2(Froyo)必须使用Asynctask

这是理解AsyncTask

的最佳example

答案 5 :(得分:0)

基于comeGetSome的答案,我创建了自己的实现,它与普通的ImageView类一起工作,而不是创建一个新的类UrlImageView,还提供了新的选项,比如 - 加载完成或取消时该怎么做

现在可以根据需要加载图像,就像三个loadImage方法中的任何一个

一样
       UrlImageLoader urlImageLoader=new UrlImageLoader();
       ImageView imageView=new ImageView(context);
       //load and set the image to ImageView
       urlImageLoader.loadImage(imageView, "http://www......com/.....jpg");
       //for loading a image only - load image and do any thing with the bitmap
       urlImageLoader.loadImage("http://www......com/.....jpg", new UrlImageLoader.OnLoadingCompleteListener() {

            @Override
            public void onComplete(ImageView imageView, Bitmap bmp) {
                // do anything with the Bitmap
                // here imageView will be null
            }
            @Override
            public void onCancel(ImageView imageView) {

            }
        });
       urlImageLoader.loadImage(imageView, "http://www......com/.....jpg", new UrlImageLoader.OnLoadingCompleteListener() {

            @Override
            public void onComplete(ImageView imageView, Bitmap bmp) {
                // do anything with the Bitmap
                // here imageView is not null
                imageView.setImageBitmap(bmp);
            }
            @Override
            public void onCancel(ImageView imageView) {

            }
        });

创建此类以加载UrlImageLoader

/*special thanks to stackoverflow.com user comeGetSome for UrlImageLoadingTask code
 * question - http://stackoverflow.com/questions/14332296/how-to-set-image-from-url-using-asynctask/15797963
 * comeGetSome - http://stackoverflow.com/users/1005652/comegetsome
 */
package com.GameG.SealTheBox;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;

public class UrlImageLoader {
    public static interface OnLoadingCompleteListener {
        public void onComplete(ImageView imageView, Bitmap bmp);
        public void onCancel(ImageView imageView);
    }
    ArrayList<UrlImageLoadingTask> loadingList=new ArrayList<UrlImageLoadingTask>();
    /**
     * Loads a image from url and calls onComplete() when finished<br>
     * @Note you should manually set the loaded image to ImageView in the onComplete()
     * @param imageView
     * @param url
     * @param onComplete
     */
    public void loadImage(ImageView imageView, String url, OnLoadingCompleteListener onComplete){
        try {
            URL url2=new URL(url);
            if(imageView!=null){
                for(int i=0;i<loadingList.size();i++){
                    UrlImageLoadingTask tmptask=loadingList.get(i);
                    if(tmptask.updateView!=null && tmptask.updateView.equals(imageView)){
                        tmptask.cancel(true);
                        break;
                    }
                }
            }
            UrlImageLoadingTask loadtask=new UrlImageLoadingTask(imageView,onComplete,url);
            loadtask.execute(url2);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    /**
     * Loads a image from url and calls onComplete() when finished
     * @param url
     * @param onComplete
     */
    public void loadImage(String url, OnLoadingCompleteListener onComplete){
        loadImage(null,url,onComplete);
    }
    /**
     * Loads a image from url and sets the loaded image to ImageView
     * @param imageView
     * @param url
     */
    public void loadImage(ImageView imageView, String url){
        loadImage(imageView,url,null);
    }
    /**
     * Cancel loading of a ImageView
     */
    public void cancel(ImageView imageView){
        for(int i=0;i<loadingList.size();i++){
            UrlImageLoadingTask tmptask=loadingList.get(i);
            if(tmptask.updateView.equals(imageView)){
                loadingList.remove(i);
                tmptask.cancel(true);
                break;
            }
        }
    }
    /**
     * Cancel loading of a Url
     */
    public void cancel(String url){
        for(int i=0;i<loadingList.size();i++){
            UrlImageLoadingTask tmptask=loadingList.get(i);
            if(tmptask.url.equals(url)){
                loadingList.remove(i);
                tmptask.cancel(true);
                break;
            }
        }
    }
    /**
     * Cancel all loading tasks 
     */
    public void cancelAll(){
        while(loadingList.size()>0){
            UrlImageLoadingTask tmptask=loadingList.get(0);
            loadingList.remove(tmptask);
            tmptask.cancel(true);
        }
    }

    private class UrlImageLoadingTask extends AsyncTask<URL, Void, Bitmap> {
        public ImageView updateView=null;
        public String url;
        private boolean         isCancelled = false;
        private InputStream     urlInputStream;
        private OnLoadingCompleteListener onComplete=null;

        private UrlImageLoadingTask(ImageView updateView, OnLoadingCompleteListener onComplete, String url) {
          this.updateView=updateView;
          this.onComplete=onComplete;
          this.url=url;
        }

        @Override
        protected Bitmap doInBackground(URL... params) {
          try {
            URLConnection con = params[0].openConnection();
            // can use some more params, i.e. caching directory etc
            con.setUseCaches(true);
            this.urlInputStream = con.getInputStream();
            return BitmapFactory.decodeStream(urlInputStream);
          } catch (IOException e) {
            Log.w(UrlImageView.class.getName(), "failed to load image from " + params[0], e);
            return null;
          } finally {
            if (this.urlInputStream != null) {
              try {
                this.urlInputStream.close();
              } catch (IOException e) {
                ; // swallow
              } finally {
                this.urlInputStream = null;
              }
            }
          }
        }

        @Override
        protected void onPostExecute(Bitmap result) {
          if (!this.isCancelled) {
            // hope that call is thread-safe
              if(onComplete==null){
                  if(updateView!=null)
                  this.updateView.setImageBitmap(result);
              }else{
                  onComplete.onComplete(updateView, result);
              }
          }
          loadingList.remove(this);
        }

        /*
         * just remember that we were cancelled, no synchronization necessary
         */
        @Override
        protected void onCancelled() {
          this.isCancelled = true;
          try {
            if (this.urlInputStream != null) {
              try {
                this.urlInputStream.close();
              } catch (IOException e) {
                ;// swallow
              } finally {
                this.urlInputStream = null;
              }
            }
          } finally {
            super.onCancelled();
            if(onComplete!=null)
                onComplete.onCancel(updateView);
            loadingList.remove(this);
          }
        }
      }

}

答案 6 :(得分:0)

只需创建一个新类&#34; DownloadImageTask &#34;比如关注一个并将其放在您拥有活动的同一文件夹中。

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.widget.ImageView;
import android.os.AsyncTask;
import java.io.*;


public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    ImageView bmImage;

    public DownloadImageTask(ImageView bmImage) {
        this.bmImage = bmImage;
    }

    protected Bitmap doInBackground(String... urls) {
        String urldisplay = urls[0];
        Bitmap myImage = null;
        try {
            InputStream in = new java.net.URL(urldisplay).openStream();
            myImage = BitmapFactory.decodeStream(in);
        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }
        return myImage;
    }

    protected void onPostExecute(Bitmap result) {
        bmImage.setImageBitmap(result);
    }
}

在此活动之后添加行以创建该类。

import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.util.Log;
import android.widget.ImageView;


public class HomeScreen extends ActionBarActivity {

    private final String TAG = "test1";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
        setContentView(R.layout.activity_home_screen);
        InitHomeScreen();
    }

    protected void InitHomeScreen()
    {
        String imageUrl = "http://s20.postimg.org/4t9w2pdct/logo_android_png.png";
        Log.d(TAG, "Get an Image");
        // Get an Image
        try{
            AsyncTask<String, Void, Bitmap> execute = new DownloadImageTask((ImageView) findViewById(R.id.imageView))
                    .execute(imageUrl);
              // R.id.imageView  -> Here imageView is id of your ImageView
        }
        catch(Exception ex)
        {
        }
    }

   // Other code...

不要忘记允许访问INTERNET到您的Android应用程序。

检查您的清单文件。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.dmitry.myapplication1" >

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".HomeScreen"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>