2011-10-25 4 views
0

Android 개발의 일반적인 작업은 웹에서 이미지를로드하고 활동의 ImageView로 바인딩하는 것입니다. 내가 본 프로그래머는 AsyncTask를 사용하여 배경에서로드를 실행하고 컨텍스트에서 결과를 게시하는 것을 보았습니다. 이 접근법은 오리엔테이션이 바뀌는 것처럼 어떤 경우에는 응용에 대한 갈망을 유도합니다. 원인은 상황입니다. 활동이 파괴되어 다시 생성되기 때문에 으로 손실되지만 실행중인 AsyncTask 컨텍스트는 업데이트되지 않습니다. 그래서 postExectute가 호출 될 때 AsyncTask는 이 더 이상 존재하지 않는 결과를 Activity에 게시하려고 시도합니다..Android : AsyncTask를 사용하지 않고 웹에서 이미지를로드하는 가장 좋은 방법은 무엇입니까?

데이터를 이미지로로드 한 다음 활동으로 게시하는 데 어떤 접근 방식을 사용하고 있는지 알고 싶습니다.

답변

4

전화 번호는 AsyncTaskLoader입니다. 그것은 AsycnTask와 비슷합니다. 단, 전체적으로 "활동이 멈출 때 AsyncTask를 삭제해야합니다."비트가 당신을 대신해주는 것입니다. 로더는 일반적으로 목록 뷰에 대한 데이터를 비동기 적으로로드하는 작업을 향상시키기 위해 특별히 설계되었습니다. 사실, 그들은 빨리 내가 ​​좋아하는 새로운 안드로이드 클래스 중 하나가 될 수 있습니다. 로더에 대한 자세한 내용은 documentation을 확인하십시오.

최종 메모로서, API 레벨 10까지는 로더가 도입되지 않았습니다. 그렇다고해도 android 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

이 질문은 현재 해결되지 않은 질문입니다. 질문자는 방향이 바뀔 때 AsyncTasks를 처리하는 방법을 알고 싶어합니다. 이것은 단지 이미지를 다운로드하는 방법을 보여줍니다. –

+0

답변 해 주신 Hitendra와 귀하의 댓글 Kurtis에 감사드립니다. 내 목표는 위에서 설명한 케이스에서 좋은 접근 방식을 찾는 것입니다. 컨텍스트가 손실되었을 때 우리는 acynTask를 처리 할 수 ​​있지만 그래야합니까? 내 말은, 그것은 정말로 최선의 접근 방법인가? 예, 그렇지 않을 수도 있습니다. 그래서 안드로이드 개발자가 자신의 experinece을 공유하기 위해 wnat 수 있습니다. 그게 내 질문에 관한거야. – user1012050

+0

kurtis, 여기 user1012050의 질문입니다. 나는 당신이 사유지로서의 자료를로드하고 활동에 게시하기 위해 어떤 접근법을 사용하고 있는지 알고 싶습니까? 특별한 접근법 (예 : asynctask)을 보여주지 않습니다. – Hitendra

관련 문제