http://dktfrmaster.blogspot.kr/2018/
java.lang.Thread
클래스가 모든 스레드의 근간이 된다.Thread.State
enum에 정의되어 있으며, Thread 인스턴스의 getStatus()
메서드를 이용해 확인할 수 있다.Thread.start()
메서드가 호출되어 실행환경이 설정된 직후부터 스레드가 실행되는 중의 상태run()
메서드가 호출되어 태스크가 실행된다.run()
메서드가 실행을 완료하면 스레드가 종료되고 스레드의 자원이 해제된 후의 상태interrupt()
메서드 호출interrupt()
메서드를 이용해 인터럽트를 요청class TestThread extends Thread {
@Override
public void run() {
//isInterrupt() 메서드를 수시로 검사하여 true를 반환하면 태스크를 완료한 것으로 처리
while(!isInterrunpted()) {
//스레드가 살아있음
}
//태스크 완료되어 스레드 종료됨
}
}
InterruptException
을 던진다.class TestThread extends Thread {
@Override
public void run() {
//isInterrupt() 메서드를 수시로 검사하여 true를 반환하면 태스크를 완료한 것으로 처리
while(!isInterrunpted()) {
doBlockingAction();
}
}
public void doBlockingAction() {
try {
//Blocking API 호출
} catch (InterruptException e) {
//1.자원 정리
//2.isInterrupt() 플래그가 초기화되었으므로, run() 메서드가 isInterrupt()를 제대로 인식하도록 자신을 다시 인터럽트
Thread.currentThread().interrupt();
}
}
}
RuntimeException
을 잡으려면, 스레드가 비정상 종료되기 전에 호출되는 UncaughtExceptionHandler
를 부착한다.setDefaultUncaughtExceptionHandler()
정적 메서드 호출setUncaughtExceptionHandler()
메서드 호출// 앱 시작시 실행되는 아무 클래스
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate(0;
//새로운 전역 핸들러를 설정
Thread.setDefaultUncaughtExceptionHandler(new LogExceptionHandler());
}
}
//새로 정의한 예외핸들러 클래스
public class LogExceptionHandler implements Thread.UncaughtExceptionHandler {
private final Thread.UncaughtExceptionHandler defaultHandler;
public LogExceptionHandler() {
defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
}
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
//로그를 파일로 남기거나 서버로 전송
//안드로이드 런타임이 붙였던 기존 핸들러로 작업 위임
default.Handler.uncaughtException(thread, throwable);
}
}
public class AnyObject {
//UI 스레드에서 호출되는 메서드
@UiThread
public void anyMethod() {
new Thread() {
@Override
public void run() {
// 긴 태스크를 실행한다고 가정
// 해당 스레드가 살아있는 동안 이 스레드는 AnyObject 인스턴스의 참조를 유지하고 있다.
doLongRunningTask();
}
}.start();
}
}
class TestThread extends Thread {
@Override
public void run() {
// 긴 태스크를 실행한다고 가정
doLongRunningTask();
}
}
public class AnyObject {
//UI 스레드에서 호출되는 메서드
private TestThread testThread;
@UiThread
public void anyMethod() {
testThread = new TestThread();
testThread.start();
}
}
public class AnyObject {
static class TestThread extends Thread {
@Override
public void run() {
// 긴 태스크를 실행한다고 가정
doLongRunningTask();
}
}
private TestThread testThread;
//UI 스레드에서 호출되는 메서드
@UiThread
public void anyMethod() {
testThread = new TestThread();
testThread.start();
}
}
onRetainNonConfigurationInstance()
메서드에서 반환한 객체를 반환한다.public class TestActivity extends Activity {
private static class TestThread extends Thread {
@Override
public void run() {
//TODO::긴 작업
}
}
private static TestThread thread;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout_activity_test);
Object retainedObject = getLastNonConfigurationInstance();
if (retainedObject != null) {
thread = retainedObject;
} else {
thread = new TestThread();
thread.start();
}
}
@Override
public Object onRetainNonConfigurationInstance() {
if (thread != null && thread.isAlive()) {
return thread;
}
return null;
}
}
setRetainInstance(true)
를 이용하여 프레그먼트를 유지한다.public class TestFragment extends Fragment {
private static class TestThread extends Thread {
@Override
public void run() {
//TODO::긴 작업
}
}
private TestThread thread;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (thread == null) {
thread = new Thread();
thread.start();
}
// 이 메서드만 설정해주면 프레그먼트는 엑티비티의 설정이 변경되는 동안 객체가 유지된다.
setRetainInstance(true);
}
}
public class TestActivity extends Activity {
TestFragment fragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout_activity_test);
FragmentManager manager = getFragmentManager();
fragment = manager.findFragmentByTag("TestFragment");
if (fragment == null) {
FragmentTransaction transaction = manager.beginTransaction();
fragment = new Fragment();
transaction.add(fragment, "TestFragment");
transaction.commit();
}
}
}