2010-06-22 3 views
31

Как заменить следующие строки кода на Asynctask? Как вы «возвращаете» битмап из Asynctask? Спасибо.Android: Загрузка изображения из Интернета с помощью Asynctask

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

mChart.setImageBitmap(download_Image(URL)); 

public static Bitmap download_Image(String url) { 

     //--------------------------------------------------- 
     Bitmap bm = null; 
     try { 
      URL aURL = new URL(url); 
      URLConnection conn = aURL.openConnection(); 
      conn.connect(); 
      InputStream is = conn.getInputStream(); 
      BufferedInputStream bis = new BufferedInputStream(is); 
      bm = BitmapFactory.decodeStream(bis); 
      bis.close(); 
      is.close(); 
     } catch (IOException e) { 
      Log.e("Hub","Error getting the image from server : " + e.getMessage().toString()); 
     } 
     return bm; 
     //--------------------------------------------------- 

    } 

Я думал о чем-то вроде этого:

заменить:

mChart.setImageBitmap(download_Image(graph_URL)); 

что-то вроде:

mChart.setImageBitmap(new DownloadImagesTask().execute(graph_URL)); 

и

public class DownloadImagesTask extends AsyncTask<String, Void, Bitmap> { 

@Override 
protected Bitmap doInBackground(String... urls) { 
    return download_Image(urls[0]); 
} 

@Override 
protected void onPostExecute(Bitmap result) { 
    mChart.setImageBitmap(result);    // how do I pass a reference to mChart here ? 
} 


private Bitmap download_Image(String url) { 
    //--------------------------------------------------- 
    Bitmap bm = null; 
    try { 
     URL aURL = new URL(url); 
     URLConnection conn = aURL.openConnection(); 
     conn.connect(); 
     InputStream is = conn.getInputStream(); 
     BufferedInputStream bis = new BufferedInputStream(is); 
     bm = BitmapFactory.decodeStream(bis); 
     bis.close(); 
     is.close(); 
    } catch (IOException e) { 
     Log.e("Hub","Error getting the image from server : " + e.getMessage().toString()); 
    } 
    return bm; 
    //--------------------------------------------------- 
} 


} 

но Как передать ссылку на mChart в onPostExecute (результат Bitmap) ??? Должен ли я передать его с URL-адресом в некотором роде? Я хотел бы заменить все мои строки кода:

mChart1.setImageBitmap(download_Image(URL_1)); 
mChart2.setImageBitmap(download_Image(URL_2)); 

нечто подобное ... но в AsyncTask пути!

mChart1.setImageBitmap(new DownloadImagesTask().execute(graph_URL_1)); 
mChart2.setImageBitmap(new DownloadImagesTask().execute(graph_URL_2)); 

Есть ли легкое решение для этого? У меня что-то не так?

+0

довольно основной вопрос, но было бы полезно для многих начинающих, как я, я думаю ... пожалуйста, отправьте код, если у вас есть. – Hubert

+0

Связанный: пример [ImageDownloader] (http://developer.android.com/resources/samples/XmlAdapters/src/com/example/android/xmladapters/ImageDownloader.html) – idbrii

+0

@Hubert может уделить вам упоминание частного Bitmap download_Image (String url) { ... } этот код? – Erum

ответ

65

Если у вас нет веской причины скачивать изображения самостоятельно, тогда я рекомендую использовать Picasso.

Picasso избавляет вас от всех проблем с загрузкой, настройкой и кэшированием изображений. Всего кода, необходимый для простого примера:

Picasso.with(context).load(url).into(imageView); 

Если вы действительно хотите сделать все самостоятельно использовать старший ответ ниже.

Если изображение не такое большое, вы можете просто использовать анонимный класс для задачи async. Это нравится:

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) { 
    ... 
} 

Скрытие URL в теге немного сложнее, но она выглядит лучше в классе вызывающего, если у вас есть много imageviews что вы хотите заполнить этот путь. Это также помогает, если вы используете ImageView внутри ListView и хотите узнать, был ли ImageView переработан во время загрузки изображения.

Я написал, если вы не так значительны, потому что это приведет к тому, что задача будет иметь неявный указатель на базовое действие, в результате чего сборщик мусора будет удерживать всю активность в памяти до завершения задачи. Если пользователь переместится на другой экран вашего приложения, а загрузка растрового изображения не может быть освобождена, это может привести к замедлению вашего приложения и всей системы.

+0

мои изображения - это что-то вроде 45.2 Ko (46,384 октетов) типа gif, если это имеет значение? – Hubert

+0

Это проблема только в том случае, если требуется больше времени, чем 20 секунд, чтобы загрузить изображения, и ваша активность тяжела в системной памяти. – Janusz

+0

Спасибо Януш, я сделал EDIT моего вопроса с некоторыми добавленными вещами. Как вы думаете ? Я бы хотел использовать эту AsyncTask на разных ImageViews. Как передать правильную ссылку на ImageView в onPostExecute? Большое спасибо за вашу помощь. – Hubert

0

Это даст вам изображения любого размера ... Если вы не хотите, чтобы диалог прогресса просто комментировал коды в onPreExecute();

for(int i = 0 ; i < no_of_files ; i++) 
new FetchFilesTask().execute(image_url[i]); 


private class FetchFilesTask extends AsyncTask<String, Void, Bitmap> { 

    private ProgressDialog dialog = new ProgressDialog(FileExplorer.this); 
    Bitmap bitmap[]; 
    protected void onPreExecute(){ 
     dialog.setMessage("fetching image from the server"); 
     dialog.show(); 
    } 

    protected Bitmap doInBackground(String... args) { 

      bitmap = getBitmapImageFromServer(); 
     return bitmap; 
    } 

    protected void onPostExecute(Bitmap m_bitmap) { 
     dialog.dismiss(); 
     if(m_bitmap != null) 
      //store the images in an array or do something else with all the images. 
    } 
} 

public Bitmap getBitmapImageFromServer(){ 

    // fetch image form the url using the URL and URLConnection class 
} 
+1

Спасибо, Умеш за ваше предложение. Может быть, я действительно должен добавить ProgressDialog, на всякий случай! Но как бы вы передали контекст (ваш FileExplorer.this) в AsyncTask, а затем ??? Я хотел бы, чтобы мой DownloadImagesTask() мог быть доступен из любой активности моего приложения ... Я создал для него отдельный класс. – Hubert

1

вы можете создать класс say..BkgProcess, содержащий внутренний класс, который расширяет AsyncTask. в то время как экземпляр BkgProcess передает контекст вашего класса Activity в конструкторе BkgProcess. для например:

public class BkgProcess { 

String path; 
Context _context; 

public Download(Downloader downloader, String path2){ 

this.path = path2; 
    _context = downloader; 

} 

public void callProgressDialog(){ 

new BkgProcess().execute((Void)null); 
} 
class Downloads extends AsyncTask<Void, Void, Boolean> { 
    private ProgressDialog dialog = new ProgressDialog(_context); 
    protected void onPreExecute(){ 
     dialog.setMessage("Downloading image.."); 
     dialog.show(); 
    } 

    protected void onPostExecute(Boolean success) { 
     dialog.dismiss(); 
     if(success) 
      Toast.makeText(_context, "Download complete", Toast.LENGTH_SHORT).show(); 
    } 

@Override 
protected Boolean doInBackground(Void... params) { 
    return(startDownload(path)); 

    } 


public boolean startDownload(String img_url) { 

// download img.. 

     return true; 
} 
} 
} 

из вашего класса активности ..

BkgProcess dwn = new BkgProcess (Your_Activity_class.this, img_path); 

dwn.callProgressDialog(); 
18

Попробуйте этот код:

ImageView myFirstImage = (ImageView) findViewById(R.id.myFirstImage); 
ImageView mySecondImage = (ImageView) findViewById(R.id.mySecondImage); 
ImageView myThirdImage = (ImageView) findViewById(R.id.myThirdImage); 

String URL1 = "http://www.google.com/logos/2013/estonia_independence_day_2013-1057005.3-hp.jpg"; 
String URL2 = "http://www.google.com/logos/2013/park_su-geuns_birthday-1055005-hp.jpg"; 
String URL3 = "http://www.google.com/logos/2013/anne_cath_vestlys_93rd_birthday-1035005-hp.jpg"; 


myFirstImage.setTag(URL1); 
mySecondImage.setTag(URL2); 
myThirdImage.setTag(URL3); 


new DownloadImageTask.execute(myFirstImage); 
new DownloadImageTask.execute(mySecondImage); 
new DownloadImageTask.execute(myThirdImage); 



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) { 

     Bitmap bmp =null; 
     try{ 
      URL ulrn = new URL(url); 
      HttpURLConnection con = (HttpURLConnection)ulrn.openConnection(); 
      InputStream is = con.getInputStream(); 
      bmp = BitmapFactory.decodeStream(is); 
      if (null != bmp) 
       return bmp; 

      }catch(Exception e){} 
     return bmp; 
    } 
} 
+0

'return download_Image ((String) imageView.getTag());' дает ошибку. 'getTag должен вызываться из потока пользовательского интерфейса' – XoXo

Смежные вопросы