2011-10-25 16 views
0

Android開発の一般的なタスクは、Webから画像を読み込んで、Activity内のImageViewでバインドすることです。私が見ていたコードでは、プログラマーはAsyncTaskを使用して、バックグラウンドで読み込みを実行し、コンテキストで結果を投稿することがよくあります。 このアプローチは、オリエンテーションの変化として、いくつかのケースでは、アプリケーションを渇望することにつながります。原因は文脈です。アクティビティが破棄されて再び作成される可能性があるため、コンテキストもとなり、が失われますが、実行中のAsyncTaskコンテキストは更新されません。したがって、postExectuteが呼び出されると、AsyncTaskは、が存在しない結果をActivityに投稿しようとします。Android:AsyncTaskを使わずにWebから画像を読み込む最良の方法は何ですか?

データを画像として読み込んでアクティビティに投稿する方法を知りたいのですが?

答えて

4

あなたはAsyncTaskLoaderと呼ばれるものを使用してみるべきです。 AsycnTaskと似ていますが、「アクティビティが死んだときにAsyncTaskを削除する必要があります」というビット全体があなたにとって面倒です。一般に、ローダーは、リストビューのデータを非同期にロードする作業を改善するために設計されています。実際、彼らはすぐに私の好きなAndroidの新しいAndroidのクラスの一つになりました。ローダーの詳細については、documentationをご確認ください。

最後に、ローダーはAPIレベル10まで導入されていませんでした。つまり、アンドロイドSupport Packageを使用して、より低いAPIレベルからでもローダーにアクセスできます。

0

イメージをバックグラウンドで読み込み、イメージがすでにそこにあるsdcard.ifに格納する完全なコードは次のとおりです。サーバーに要求しません。 package com.packsmooch.utils;

Albumartloader albumartloader=new Albumartloader(this); 
imageview.settag(urlofimage); 
albumartloader.DisplayImage(url of image,activity context,imageview); 

ベスト用法:ここ

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.URL; 
import java.util.HashMap; 
import java.util.Stack; 


import android.app.Activity; 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.widget.ImageView; 

public class Albumartloader 
{ 
    private HashMap<String, Bitmap> cache = new HashMap<String, Bitmap>(); 

    private File cacheDir; 
    private Bitmap useThisBitmap; 

    public Albumartloader(Context context) 
    { 
     photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1); 
     if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) 
      cacheDir = new File(android.os.Environment.getExternalStorageDirectory(),"Streaming_Service/AlbumArt/"); 
     else 
      cacheDir = context.getCacheDir(); 

     if (!cacheDir.exists()) 
      cacheDir.mkdirs(); 
    } 

    public void DisplayImage(String url, Activity activity, ImageView imageView) 
    { 
     if(!url.equals("")) 
     { 
      if (cache.containsKey(url)) 
      { 
       imageView.setImageBitmap(cache.get(url)); 
      } 
      else 
      { 
       queuePhoto(url, activity, imageView); 
      } 
     } 
    } 

    private void queuePhoto(String url, Activity activity, ImageView imageView) 
    { 
     photosQueue.Clean(imageView); 
     PhotoToLoad p = new PhotoToLoad(url, imageView); 

     synchronized (photosQueue.photosToLoad) 
     { 
      photosQueue.photosToLoad.push(p); 
      photosQueue.photosToLoad.notifyAll(); 
     } 

     // start thread if it's not started yet 
     if (photoLoaderThread.getState() == Thread.State.NEW) 
      photoLoaderThread.start(); 
    } 

    public Bitmap getBitmap(String url) 
    { 
     try 
     { 
      // I identify images by hashcode. Not a perfect solution, good for the 
      // demo. 
      String filename = String.valueOf(url.hashCode()); 
      File f = new File(cacheDir, filename); 

      // from SD cache 
      Bitmap b = decodeFile(f); 
      if (b != null) 
       return b; 

      // from web 
      try { 
       Bitmap bitmap = null;  
       if(!url.equals("")){ 
       InputStream is = new URL(url).openStream(); 
       OutputStream os = new FileOutputStream(f); 
       Utils.CopyStream(is, os); 
       os.close(); 
       bitmap = decodeFile(f); 
       } 
       return bitmap; 
      } catch (Exception ex) { 
       ex.printStackTrace(); 
       return null; 
      } 
     } 
     catch(Exception e) 
     { 
      return null;  
     } 
    } 

    /*decodes image and scales it to reduce memory consumption 
    * @param file path 
    * @throws FileNotFoundException 
    * @return bitmap 
    * */ 
    private Bitmap decodeFile(File f){ 
     Bitmap b = null; 
     try { 

      useThisBitmap = null; 
      //Decode image size 
      BitmapFactory.Options o = new BitmapFactory.Options(); 
      o.inJustDecodeBounds = true; 
      final int IMAGE_MAX_SIZE =50; 
      BitmapFactory.decodeStream(new FileInputStream(f), null, o); 
      int scale = 2; 
      if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) { 
       scale = 2^(int) Math.ceil(Math.log(IMAGE_MAX_SIZE/(double) Math.max(o.outHeight, o.outWidth))/Math.log(0.5)); 
      } 

      //Decode with inSampleSize 
      BitmapFactory.Options o2 = new BitmapFactory.Options(); 

      o2.inSampleSize = scale; 
      b = BitmapFactory.decodeStream(new FileInputStream(f), null, o2); 
      useThisBitmap = b; 

     } catch (FileNotFoundException e) { 

     } 
     catch(Exception e) 
     { 

     } 
     finally{ 
      System.gc(); 
     } 
     return useThisBitmap; 
    } 


    // Task for the queue 
    private class PhotoToLoad 
    { 
     public String url; 
     public ImageView imageView; 

     public PhotoToLoad(String u, ImageView i) { 
      url = u; 
      imageView = i; 
     } 
    } 

    PhotosQueue photosQueue = new PhotosQueue(); 

    public void stopThread() 
    { 
     photoLoaderThread.interrupt(); 
    } 

    // stores list of photos to download 
    class PhotosQueue { 
     private Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>(); 

     // removes all instances of this ImageView 
     public void Clean(ImageView image) { 
      for (int j = 0; j < photosToLoad.size();) { 
       if (photosToLoad.get(j).imageView == image) 
        photosToLoad.remove(j); 
       else 
        ++j; 
      } 
     } 
    } 

    class PhotosLoader extends Thread { 
     public void run() { 
      try { 
       while (true) { 
        // thread waits until there are any images to load in the 
        // queue 
        if (photosQueue.photosToLoad.size() == 0) 
         synchronized (photosQueue.photosToLoad) { 
          photosQueue.photosToLoad.wait(); 
         } 
        if (photosQueue.photosToLoad.size() != 0) { 
         PhotoToLoad photoToLoad; 
         synchronized (photosQueue.photosToLoad) { 
          photoToLoad = photosQueue.photosToLoad.pop(); 
         } 
         Bitmap bmp = getBitmap(photoToLoad.url); 
         cache.put(photoToLoad.url, bmp); 
         if (((String) photoToLoad.imageView.getTag()) 
           .equals(photoToLoad.url)) { 
          BitmapDisplayer bd = new BitmapDisplayer(bmp, 
            photoToLoad.imageView); 
          Activity a = (Activity) photoToLoad.imageView 
            .getContext(); 
          a.runOnUiThread(bd); 
         } 
        } 
        if (Thread.interrupted()) 
         break; 
       } 
      } catch (InterruptedException e) { 
       // allow thread to exit 
      } 
     } 
    } 

    PhotosLoader photoLoaderThread = new PhotosLoader(); 

    // Used to display bitmap in the UI thread 
    class BitmapDisplayer implements Runnable { 
     Bitmap bitmap; 
     ImageView imageView; 

     public BitmapDisplayer(Bitmap b, ImageView i) { 
      bitmap = b; 
      imageView = i; 
     } 

     public void run() 
     { 
      if (bitmap != null) 
       imageView.setImageBitmap(bitmap); 
     } 
    } 

    public void clearCache() 
    { 
     // clear memory cache 
     cache.clear(); 
     // clear SD cache 
     File[] files = cacheDir.listFiles(); 
     for (File f : files) 
      f.delete(); 
    } 
} 

は、使用され、サーバーからの画像の数を表示し、ダウンロードするには、すべての画像を待ちたいいけないする必要がある場合 - あなたは、リストビューのためにそれを使用することができます。

+0

これは手元の問題に対処していません。 Questionerは、向きが変わったときにAsyncTasksを処理する方法を知りたいと思っています。これはイメージをダウンロードする方法を示しています。 –

+0

あなたの答えHitendraとあなたのコメントKurtisをありがとう。私の目的は、私が上記のケースで良いアプローチを見つけることです。コンテキストが失われても私たちはacynTaskを処理できますか?本当に最善のアプローチですか?はい、いいかもしれません。だから、アンドロイドの開発者が自分の経験を分かち合うことができます。それは私の質問についてです。 – user1012050

+0

kurtis、ここにuser1012050からの質問があります。私は、あなたがinagesとしてデータを読み込むためにどのようなアプローチを使用しているのか、Activityに投稿しているのかを知りたいのですか?具体的なアプローチ(例:asynctask)は表示されません。 – Hitendra

関連する問題