Android 에서 비동기 로 그림 불 러 오기

멜 로 가 블 로 그 를 개설 한 이래 한동안 블 로 그 를 갱신 하지 않 았 다.주로 멜 로 는 그 동안 프로젝트 개발 로 인해 너무 바 빴 다.오늘 토요일 에 도 회사 에서 잔업 을 하고 프로그램 원숭이 들 이 이렇게 생활 하도록 강요 했다.
오늘 프로젝트 를 할 때 비동기 로 그림 을 불 러 오 는 기능 이 있 습 니 다.간단 하지만 기록 해 보 세 요.멜 로 이전에 비동기 로 그림 을 불 러 오 는 것 은 모두 AsynTask 라 는 API 를 사 용 했 기 때 문 입 니 다.이 종 류 를 계속 하면 매우 간단 하고 편리 합 니 다.doInBackground()방법 에서 다운로드 논 리 를 실현 합 니 다.구체 적 으로 다음 과 같이 실현 합 니 다.
논리 구현:메모리 에서 먼저 읽 고 메모리 에 이 그림 이 있 으 면 직접 사용 합 니 다.메모리 가 sdcard 에서 읽 히 지 않 으 면 표시 합 니 다.sdcard 에 없 으 면 네트워크 에서 읽 습 니 다.메모리 에 캐 시 를 켜 는 것 은 인터넷 의 실현 을 참고 한 것 입 니 다.멜 로 는 여기 서 공유 하 는 프로그램 원숭이 들 에 게 감 사 드 립 니 다.

public class ImageDownloader extends AsyncTask<String, Integer, Object> {

  private static final String TAG = "ImageDownloader";
  //       ,        (            ,             ,   ListView     )
  private Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
  /**
   *        
   */
  private ImageView mImageView;

  public ImageDownloader(ImageView image) {
    mImageView = image;
  }

  @Override
  protected void onPreExecute() {
    super.onPreExecute();
  }

  @Override
  protected Object doInBackground(String... params) {
    // Log.i("ImageDownloader", "loading image...");
    String url = params[0];
    Drawable drawable = null;
    try {
      if (!"".equals(url) && url != null) {
        String fileName = url.hashCode()+".jpg";
        //               
        if (imageCache.containsKey(fileName)) {
          SoftReference<Drawable> softReference = imageCache.get(fileName);
          drawable = softReference.get();
          if (drawable != null) {
            return drawable;
          }
        }
        File dir = new File(FileConstant.IMAGE_FILE_PATH);
        if (!dir.exists()) {
          boolean m = dir.mkdirs();
        }
        File file = new File(dir, fileName);
        if (file.exists() && file.length() > 0) {
          Log.i(TAG, "load image from sd card");
          //            sdcard
          drawable = readFromSdcard(file);
        } else {
          //file.createNewFile();
          Log.i(TAG, "load image from network");
          URL imageUrl = new URL(url);
          //   sdcard
          if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            saveImageFile(imageUrl, file);
            drawable = Drawable.createFromStream(new FileInputStream(file), fileName);
          }else{
            //      
            drawable = Drawable.createFromStream(imageUrl.openStream(), fileName);
          }
        }
        if(drawable!=null){
          //      
          imageCache.put(fileName, new SoftReference<Drawable>(drawable));
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    } 
    return drawable;
  }
  /**
   * save image
*/
  private void saveImageFile(URL url, File file) {
    FileOutputStream out = null;
    InputStream in = null;
    try {
      file.deleteOnExit();
      out = new FileOutputStream(file);
      in = url.openStream();
      byte[] buf = new byte[1024];
      int len = -1;
      while((len = in.read(buf))!=-1){
        out.write(buf, 0, len);
        out.flush();
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if(out!=null){
        try {
          out.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      if(in!=null){
        try {
          in.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }

  /**
   *  sdcard     
*/
  private Drawable readFromSdcard(File file) throws Exception {
    FileInputStream in = new FileInputStream(file);
    return Drawable.createFromStream(in, file.getName());
  }

  @Override
  protected void onPostExecute(Object result) {
    super.onPostExecute(result);
    Drawable drawable = (Drawable) result;
    if (mImageView != null && drawable != null) {
      mImageView.setBackgroundDrawable(drawable);
    }
  }

  @Override
  protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
  }

  @Override
  protected void onCancelled() {
    super.onCancelled();
  }

}

사용 시:

ImageDownloader loader = new ImageDownloader(imageView);
loader.execute(url);
사실 이렇게 되면 위험 도 있 습 니 다.즉,이러한 종류의 실현 에 문제 가 있 습 니 다.예 를 들 어 매번 imageView 에 네트워크 에 있 는 그림 을 설정 할 때 이런 종류의 메모리 캐 시 를 사용 하지 않 은 것 이 바로 imageCache 입 니 다.
Map> imageCache = new HashMap>();
imageView 를 설정 할 때마다 new 이미지 다운 로 더 의 대상 이 되 었 기 때문에 모든 이미지 다운 로 더 대상 에는 하나의 imageCache 가 독립 되 어 있 습 니 다.
또한,AsynTask 도 하나의 스 레 드 입 니 다.매번 사용 할 때마다 하나의 스 레 드 를 열 어 그림 을 로드 합 니 다.스 레 드 개 수 를 표시 하지 않 았 습 니 다.스 레 드 수 는 제한 이 있 기 때 문 입 니 다.
그래서 멜 로 는 오늘 이 문 제 를 발 견 했 습 니 다.그래서 다른 사람의 실현 을 참고 하여 스 레 드 탱크 를 사 용 했 습 니 다.논리 도 위의 코드 와 같이 메모리 에서 먼저 읽 었 습 니 다.만약 에 sdcard 에서 읽 지 않 았 다 면 없 었 다 면 네트워크 에서 읽 었 습 니 다.AsynTask 를 사용 하지 않 았 습 니 다.구체 적 인 코드 는 다음 과 같 습 니 다.

/**
 *       ,       ImageView   
*/
public class ImageDownloader extends AsyncTask<String, Integer, Object> {

  private static final String TAG = "ImageDownloader";
  //       ,        (            ,             ,   ListView     )
  private Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
  /**
   *        
   */
  private ImageView mImageView;

  public ImageDownloader(ImageView image) {
    mImageView = image;
  }

  @Override
  protected void onPreExecute() {
    super.onPreExecute();
  }

  @Override
  protected Object doInBackground(String... params) {
    // Log.i("ImageDownloader", "loading image...");
    String url = params[0];
    Drawable drawable = null;
    try {
      if (!"".equals(url) && url != null) {
        String fileName = url.hashCode()+".jpg";
        //               
        if (imageCache.containsKey(fileName)) {
          SoftReference<Drawable> softReference = imageCache.get(fileName);
          drawable = softReference.get();
          if (drawable != null) {
            return drawable;
          }
        }
        File dir = new File(FileConstant.IMAGE_FILE_PATH);
        if (!dir.exists()) {
          boolean m = dir.mkdirs();
        }
        File file = new File(dir, fileName);
        if (file.exists() && file.length() > 0) {
          Log.i(TAG, "load image from sd card");
          //            sdcard
          drawable = readFromSdcard(file);
        } else {
          //file.createNewFile();
          Log.i(TAG, "load image from network");
          URL imageUrl = new URL(url);
          //   sdcard
          if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            saveImageFile(imageUrl, file);
            drawable = Drawable.createFromStream(new FileInputStream(file), fileName);
          }else{
            //      
            drawable = Drawable.createFromStream(imageUrl.openStream(), fileName);
          }
        }
        if(drawable!=null){
          //      
          imageCache.put(fileName, new SoftReference<Drawable>(drawable));
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    } 
    return drawable;
  }
  /**
   * save image
*/
  private void saveImageFile(URL url, File file) {
    FileOutputStream out = null;
    InputStream in = null;
    try {
      file.deleteOnExit();
      out = new FileOutputStream(file);
      in = url.openStream();
      byte[] buf = new byte[1024];
      int len = -1;
      while((len = in.read(buf))!=-1){
        out.write(buf, 0, len);
        out.flush();
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if(out!=null){
        try {
          out.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      if(in!=null){
        try {
          in.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }

  /**
   *  sdcard     
 */
  private Drawable readFromSdcard(File file) throws Exception {
    FileInputStream in = new FileInputStream(file);
    return Drawable.createFromStream(in, file.getName());
  }

  @Override
  protected void onPostExecute(Object result) {
    super.onPostExecute(result);
    Drawable drawable = (Drawable) result;
    if (mImageView != null && drawable != null) {
      mImageView.setBackgroundDrawable(drawable);
    }
  }

  @Override
  protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
  }

  @Override
  protected void onCancelled() {
    super.onCancelled();
  }

}

이 Image Downloader 2 의 사용 도 간단 합 니 다.

public class ImageUtil {
  /**
   * image loader
   */
  static ImageDownloader2 loader = null;
  
  /**
   * load image
*/
  public static void loadImage(String url,final ImageView imageView){
    if(loader == null){
      loader = new ImageDownloader2();
    }
    loader.loadDrawable(url, new ImageCallback() {
      
      @Override
      public void imageLoaded(Drawable imageDrawable) {
        if(imageDrawable!=null){
          imageView.setBackgroundDrawable(imageDrawable);
        }
      }
    });
  }
  
}
매번 사용 할 때마다 ImageUtil.loadImage(url,imageView)를 호출 하여 그림 url 이 이미 그림 을 표시 해 야 하 는 컨트롤 ImageView 의 인용 을 전송 하면 됩 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기