프로그래밍/android2012. 9. 20. 17:12

비동기로 이미지를 다운로드하고, 한번 받은 이미지는 캐쉬 디렉터리에 저장해둬서 두번 받지 않는다.

물론 앱이 시작할 때 캐쉬를 지워주는 작업도 해주면 좋을 듯....


다행히 리스트뷰에서도 잘 작동함



   
package kr.mintech.test.networks;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;

public class ImageDownloader
{
	private Context _context;
	private Object _callTarget;
	private String _callMethod;
	
	
	public ImageDownloader(Context $context)
	{
		super();
		_context = $context;
	}
	
	
	public ImageDownloader(Context $context, Object $target, String $method)
	{
		super();
		_context = $context;
		registerCallback($target, $method);
	}
	
	
	public void registerCallback(Object $target, String $method)
	{
		_callTarget = $target;
		_callMethod = $method;
	}
	
	
	protected void invokeCallback()
	{
		invokeCallback(_callTarget, _callMethod);
	}
	
	
	protected void invokeCallback(Object $target, String $method)
	{
		if ($target == null || $method == null)
			return;
		
		try
		{
			Class<?> kClass = $target.getClass();
			Method kInvocation = kClass.getMethod($method);
			kInvocation.invoke($target);
		} catch (Exception $e)
		{
			$e.printStackTrace();
		}
	}
	
	
	private boolean isNull(String $str)
	{
		boolean result = false;
		
		try
		{
			if ($str == null || $str.trim().length() == 0)
				result = true;
		} catch (Exception e)
		{
			result = true;
		}
		return result;
	}
	
	
	/**
	 * 이미지 불러오기
	 */
	public void loadImage(ImageView $imageview)
	{
		// tag가 없을 때
		if ($imageview.getTag() == null)
		{
			if (_callMethod != null && _callTarget != null)
			{
				invokeCallback();
			}
			return;
		}
		
		// url이 없을 
		String kUrl = $imageview.getTag().toString();
		if (isNull(kUrl))
		{
			return;
		}
		
		if (checkFile(kUrl))
		{
			loadFile($imageview);
			
			if (_callMethod != null && _callTarget != null)
			{
				invokeCallback();
			}
		}
		else
		{
			new ImageDownloadTask().execute($imageview);
		}
	}
	
	
	/**
	 * 이미지를 다운로드만 해놓기
	 * @param $url
	 */
	public void downloadImage(String $url)
	{
		if (!checkFile($url))
		{
			new ImageDownloadOnlyTask().execute($url);
		}
	}
	
	
	// 파일이 있는지 검사
	private boolean checkFile(String $url)
	{
		File kFile = new File(convertUrlToFileName($url));
		return kFile.canRead();
	}
	
	
	// url에서 / : . 을 _로 변경
	private String convertUrlToFileName(String $url)
	{
		String kResult = $url;
		
		kResult = kResult.replaceAll("\\/", "_");
		kResult = kResult.replaceAll("\\:", "_");
		kResult = kResult.replaceAll("\\.", "_");
		kResult = _context.getCacheDir() + "/" + kResult + ".jpg";
		return kResult;
	}
	
	
	// 이미지 가져오기
	private void loadFile(ImageView $imageView)
	{
		String kName = convertUrlToFileName($imageView.getTag().toString());
		Log.w("ImageDownloader | loadFile()", " : " + kName);
		$imageView.setImageDrawable(Drawable.createFromPath(kName));
	}
	
	
	// 이미지 다운받기
	private String asyncImageDownload(String $url)
	{
		String kResult = null;
		try
		{
			Log.w("ImageDownloader | asyncImageDownload()", " : " + $url);
			URL kUrl = new URL($url);
			
			HttpURLConnection kConn = (HttpURLConnection) kUrl.openConnection();
			kConn.connect();
			InputStream kIs = kConn.getInputStream();
			
			byte[] buffer = new byte[1024];
			int bufferLength = 0;
			
			File kFile = new File(convertUrlToFileName(kUrl.toString()));
			FileOutputStream kFileOutput = new FileOutputStream(kFile);
			
			while ((bufferLength = kIs.read(buffer)) > 0)
			{
				kFileOutput.write(buffer, 0, bufferLength);
			}
			kFileOutput.close();
			kConn.disconnect();
			kIs.close();
			
			kResult = kFile.toString();
		} catch (Exception e)
		{
			e.printStackTrace();
		}
		
		return kResult;
	}
	
	// ==============================
	// Listener
	// ==============================
	// 이미지뷰에 바로 표시할 용도
	private class ImageDownloadTask extends AsyncTask<ImageView, Integer, String>
	{
		private ImageView _imageView;
		
		
		@Override
		protected String doInBackground(ImageView... views)
		{
			_imageView = views[0];
			return asyncImageDownload(_imageView.getTag().toString());
		}
		
		
		@Override
		protected void onPostExecute(String $result)
		{
			super.onPostExecute($result);
			
			_imageView.setImageDrawable(Drawable.createFromPath($result));
			
			if (callMethod != null && callTarget != null)
			{
				invokeCallback();
			}
		}
	}
	
	// 다운로드만 하는 용도
	private class ImageDownloadOnlyTask extends AsyncTask<String, Integer, String>
	{
		@Override
		protected String doInBackground(String... urls)
		{
			return asyncImageDownload(urls[0]);
		}
	}
}



   
private void load()
{
	ImageView kImageView = (ImageView) findViewById(R.id.image_view);
	kImageView.setTag("https://mail.google.com/mail/u/0/images/minigoogle.png");
	new ImageDownloader().loadImage(kImageView);
	// new ImageDownloader(this, "onDownloaded").loadImage(kImageView);
}


public void onDownloaded()
{
	Log.w("###", "다운로드 완료");
}




ImageDownloader.java


Posted by 쎄미

댓글을 달아 주세요

  1. Neithard

    ImageDownloadTask 클래스의 onPostExecute에서 callMethod, callTarget 앞에 '_'가 빠진것 같은데 맞나요?
    잘 보고 갑니다. 많은 도움이 되었습니다. ^^

    2013.05.14 14:01 [ ADDR : EDIT/ DEL : REPLY ]