태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

티스토리 툴바

자문자답 코너

 

Q. AsyncTaskActivity 란?

A. 말그대로 비동기 작업을 도와주는 Activity 입니다.

Q. 왜 만들게 됬나요?

A. 안드로이드에서 ANR 요소중 가장 크게 작용하는게 메인레드에서 시간이 많이걸리는 작업을 해서 에러가 발생되는데 그 작업을 할려면 Handler , AsyncTask 같은 객체를 이용하는 방법이 있는데 이방법을 더 효율적으로 사용할려고 만들었습니다.

Q. 기능들은 뭐가 있나요?

A.

  1. Activity LifeCycle에 따른 자동 시작 , 종료
  2. Handler나 AsyncTask를 구현하지 않아도 메인스레드와 분리할수 있는 편리함
  3. ID값 기준으로 무한대로 늘릴수 있는 다양성
  4. 소스의 절약

Q. 필요성이 많아 보이나요?

A. 글쎄요.. 전 많이 활용하고 있습니다. 남들이 없어도 저만 편리하면 되져

Q. 소스공개?

A. 물론

  

package pe.mh.app;

import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;

import pe.mh.app.annotation.LifeCycleCode;
import pe.mh.app.annotation.Network;
import pe.mh.event.EventBag;
import pe.mh.memory.MemoryUtils;
import android.app.Activity;
import android.os.AsyncTask;
import android.widget.Toast;

/**
 * 비동기 작업을 좀더 쉽게 도와주는 액티비티
 * 
 * @author 도민회
 * 
 * 
 * 2012-03-27
 * 
 * 작업이 실패한 AsyncTask는 재사용을 불가한다... 
 * 무조건 한번만 실행이 되어야한다.
 * 
 *
 * @param  AsyncTask Parameter
 * @param  AsyncTask Progress 
 */
public class AsyncTaskActivity extends Activity {
	protected static final int TASK_DEFAULT = 0;
	

	private HashMap mParams;
	private HashMap mProgress;
	private HashMap mBackgroundWorkers;
	private final ArrayList mNetworkMethods;
	
	public AsyncTaskActivity() {
		mNetworkMethods = new ArrayList();
		mParams = new HashMap();
		mProgress = new HashMap();
		mBackgroundWorkers = new HashMap();
		prepareNetworkMethods();
	}
	
	public void showToast(CharSequence text) {
		Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
	}
	
	protected boolean isAsyncTask() {
		return false;
	}
	
	private void prepareNetworkMethods() {
		if (isAsyncTask() == false) {
			return;
		}
		
		for (Method method : getClass().getMethods()) {
			Network attrs = method.getAnnotation(Network.class);
			if (attrs != null) {
				mNetworkMethods.add(method);
			}
		}
	}
	
	@Override
	protected void onDestroy() {
		MemoryUtils.disponse(getWindow().getDecorView());
		super.onDestroy();
		allCancel();
	}

	@Override
	protected void onPause() {
		super.onPause();
		doCancel(LifeCycleCode.PAUSE);
	}

	@Override
	protected void onRestart() {
		super.onRestart();
		doExecute(LifeCycleCode.RESTART);
	}

	@Override
	protected void onResume() {
		super.onResume();
		doExecute(LifeCycleCode.RESUME);
	}

	@Override
	protected void onStart() {
		super.onStart();
		doExecute(LifeCycleCode.START);
	}

	@Override
	protected void onStop() {
		super.onStop();
		doCancel(LifeCycleCode.STOP);
	}
		
	void doExecute(LifeCycleCode cycle) {
		for (Method method : mNetworkMethods) {
			Network attrs = method.getAnnotation(Network.class);
			if (attrs.executeCycle() == cycle) {
				if (attrs.isAuto()) {
					BackgroundWorker worker = new BackgroundWorker(method);
					worker.execute(mParams.get(attrs.id()));
					mBackgroundWorkers.put(attrs.id(), worker);
				}
			}
		}
	}
	
	private void allCancel() {
		for (BackgroundWorker worker : mBackgroundWorkers.values()) {
			worker.cancel(true);
		}
	}
	
	void doCancel(LifeCycleCode cycle) {
		for (Method method : mNetworkMethods) {
			Network attrs = method.getAnnotation(Network.class);
			if (attrs.cancelCycle() == cycle) {
				BackgroundWorker worker = mBackgroundWorkers.get(attrs.id());
				if (worker != null) {
					worker.cancel(true);
				}
			}
		}
	}
	
	/**
	 * 파라미터 값을 추가한다.
	 * 
	 * 반드시 테스크가 시작될 주기보다 전에 등록을 해야된다..
	 * @param id 테스크 아이디 
	 * @param params 파라미터
	 */
	protected void addParams(int id , Params... params) {
		mParams.put(id, params);
	}
	
	protected void addProgress(int id , Progress... progress) {
		mProgress.put(id, progress);
	}
	
	/**
	 * 테스크를 무조건 호출한다.
	 * @param id
	 */
	protected void executeTask (int id) {
		BackgroundWorker worker = mBackgroundWorkers.get(id);
		if (worker == null) {
			for (Method method : mNetworkMethods) {
				Network attrs = method.getAnnotation(Network.class);
				if (attrs.id() == id) {
					worker = new BackgroundWorker(method);
					worker.execute(mParams.get(attrs.id()));
					mBackgroundWorkers.put(attrs.id(), worker);
				}
			}
		} else {
			if (worker.getStatus() != AsyncTask.Status.RUNNING) {
				worker.execute(mParams.get(id));
			}
		}
	}

	/**
	 * 모든 작업이 끝났을시 호출된다. 이메소드는 오버로드 해서 사용한다.
	 * @param id
	 * @param result
	 */
	protected void onExecute(int id , EventBag result) {
	}
	
	/**
	 * 작업중에 호출되는 메소드 입니다.
	 * @param values
	 */
	protected void onPogress(int id , Progress... values) {
	}
	
	private static final EventBag EMPTY = new EventBag();
	private class BackgroundWorker extends AsyncTask  {
		private WeakReference reference;
		
		BackgroundWorker (Method method) {
			reference = new WeakReference(method);
		}

		@Override
		protected EventBag doInBackground(Params... params) {
			Method method = reference.get();
			Network attrs = method.getAnnotation(Network.class);
			publishProgress(mProgress.get(attrs.id()));
			EventBag bag = EMPTY;
			try {
				Params[] ps = mParams.get(attrs.id());
				Object invoke = method.invoke(
						AsyncTaskActivity.this, new Object[] { ps });
				if (invoke instanceof EventBag) {
					bag = (EventBag)invoke;
				}
			} catch (Throwable e) {
				bag.exception = e;
			}
			return bag;
		}

		@Override
		protected void onPostExecute(EventBag result) {
			if (reference != null) {
				Method method = reference.get();
				Network attrs = method.getAnnotation(Network.class);
				onExecute(attrs.id() , result);
				//모든작업이 끝나면 삭제한다.
				//예외가 생겨도 무조건 삭제한다.!!
				mBackgroundWorkers.remove(attrs.id());
			}
		}

		@Override
		protected void onProgressUpdate(Progress... values) {
			Method method = reference.get();
			Network attrs = method.getAnnotation(Network.class);
			onPogress(attrs.id() , values);
		}
	}
}

Posted by 표독수

Trackback Address :: http://dmh11.tistory.com/trackback/167 관련글 쓰기

댓글을 달아 주세요

안드로이드에서 HTTP , FTP 같은 프로토콜에서 이미지를 받아오는 경우는 무수히 많이 존재하고 있습니다. 그만큼 캐쉬에 대한 효율성을 더욱더 중요시 되고 있는 상황이고 , 매번 커넥션해서 다 받아올때까지 기다리고 셋팅하는것은 있을수 없는일이라 생각이 되어서 제작을 하게 되었습니다.

1. ImageCache

  • 이미지에 대한 캐쉬를 메모리상에 저장하는 클래스
  • Map의 자료구조 , 직렬화

2. ImageCacheHandler

  • 이미지를 직접적으로 비동기 셋팅을 해주는 클래스
  • 로딩이미지 제공

3. ImageRepository

  • 이미지 저장소
  • ImageCacheHandler 파일로 저장
  • ImageCacheHandler 객체로 불러오기

 

Posted by 표독수

Trackback Address :: http://dmh11.tistory.com/trackback/166 관련글 쓰기

댓글을 달아 주세요


문득 예전 자료를 찾아보다가 이력서 넣을려고 작성한 이미지뷰어가 있길래 올려봅니다. 

당시 개발 시작한지 6개월 정도 됬을때 같네요 .

위에 알씨를 모티브 하여 이미지 뷰어를 만들어 볼려구 합니다. 제가 프로그램을 시작한지 얼마되지 않아서 그냥 이미지 뷰어를 만들어도 좋지만 최대한 객체지향을 중점에 두고 일정한 규칙을 이용하여 설계를 해봤습니다. 


위에 보시면 ImageViewForm 에서 목록일때와 사진을 볼때의 컨트롤을 두개로 ViewerControl , ListControl로 나누었고 ListControl에서는 알시와 같이 각각의 컨트롤로 따로 해서 만들었습니다. 


위에 사진은 목록에 해당되는 ListControl을 설계 해봤습니다. 

모든 컨트롤을 관리하고 비지니스 로직은 대리자를 통해 폼단에 위임한다.

* TreeView - 현재폴더의 위치를 Node 형식으로 제공

* ImgView - 선택된 이미지의 미리보기

* ListView - 현재 폴더의 이미지만을 표시

* SearchView - 현재 폴더의 경로




'개인프로젝트 > C#' 카테고리의 다른 글

이미지뷰어  (0) 2012/05/03
YoutubePlayer  (0) 2012/02/16
구글번역기 어플  (0) 2011/01/11
자동쿼리생성기 Ver 0.2  (0) 2011/01/06
테트리스 만들기  (0) 2011/01/04
자동 쿼리코드 생성기 Ver 0.1  (0) 2010/12/21
Posted by 표독수

Trackback Address :: http://dmh11.tistory.com/trackback/165 관련글 쓰기

댓글을 달아 주세요