Part2. 지난 시간까지는 기본적인 안드로이드 스레드, 프로세스에 대해서 설명하였다면, 이번씨간 부터는 어떤 방식으로 실제 구현하는가에 대한 초점을 맞추며 배워보도록 하자.
오늘 내용.
스레드 사용의 몇 가지 기본사항을 다루고, 안드로이드 구성요소와 협력하는 스레드에 대해 논의 하고, 스레드 관리로 마무리한다.(태스크의 취소, Activity, Fragment객체에서 스레드를 유지하는 방법)
7.1 기본 사항
안드로이드 thraed 클래스는 일반 자바 프로그래밍의 Thread클래스와 같고, Thread 클래스는Runnable로 표현되는 태스크를 위한 실행 환경을 만든다.
7.1.1 생명주기
스레드가 존재하는 동안에 나타날 수 있는 관찰 가능한 상태를 설명한다. (Thread.State)
다음과 같이 생성 -> 실행 / (차단/대기) -> 종료 순으로 설명된다.
Thread t = new SimpleThread(); t.start(); // 스레드 시작 t.interrupt(); // 인터럽트 요청
public class SimpleThread extends Thread { @Override public void run() { while(isInterrupted() == false) { //스레드가 살아 있다. } // 테스크가 완료되고 스레드가 종료된다. } }
void myMethod() { try { // 차단 호출 } catch (InterruptedException e) { // 1. 정리 작업 // 2. 다시 한 번 인터럽트 Thread.currentThread().interrupt(); } }
Thread t = new Thread(new Runnable() { @Override public void run() { throw new RuntimeException("Unexpected error Occured"); } }); t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread thread, Throwable throwable) { // 로깅 // 네트워크 전송 Log.d(TAG, throwable.toString()); } }); t.start();
public class AnyObject { @UiThread public void anyMethod() { new Thread() { public void run() { doLongRunningTask(); } }.start(); } }
class MyThread extends Thread { public void run() { doLongRunningTask(); } } public class AnyObject { private MyThread mMyThread; @UiThread public void anyMethod() { mMyThread = new MyThread(); mMyThread.start(); } }
public class AnyObject { static class MyThread extends Thread() { public void run() { doLongRunningTask(); } }; private MyThread mMyThread; @UiThread public void anyMethod() { mMyThread = new MyThread(); mMyThread.start(); } }
public class ThreadRetainActivity extends Activity { public static class MyThread extends Thread { private ThreadRetainActivity mActivity; public MyThread(ThreadRetainActivity activity) { mActivity = activity; } @Override public void run() { final String text = getTextFromNetwork(); mActivity.setText(text); } private String getTextFromNetwork() { //네트워크 시뮬레이션 SystemClock.sleep(5000); return "text from network"; } } private static MyThread t; private TextView textView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_retain_thread); textView = (TextView) findViewById(R.id.text_retain); Object retainedObject = getLastNonConfigurationINstance(); if(retainedObject != null) { t = (MyThread) retainedObejct; t.attach(this); } } @Override public Object onRetainNonConfigurationInstance() { if ( t != null && t.isAlive()) { return t; } return null; } public void onClickStartThread(View v) { t = new MyThread(this); t.start(); } private void setText(final String text) { runOnUiThread(new Runnable() { @Override public void run() { textView.setText(text); } }); } }
public class ThreadRetainWithFragmentActivity extends Activity { private ThreadFragment mThreadFragment; private TextView mTextView; public void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_retain_thread); mTextView = (TextView) findViewById(R.id.text_retain); FragmentManager manager = getFragmentManager(); mThreadFragment = (ThreadFragment) manager.findFragmentByTag("threadfragment"); if (mThreadFragment == null) { FragmentTransaction transaction = manager.beginTransaction(); mThreadFragment = new ThreadFragment(); transaction.add(mThreadFragment, "threadfragment"); transaction.commit(); } } public void onStartThread(View v) { mThreadFragment.execute(); } public void setText(final String text) { runOnUiThread(new Runnalbe() { @Override public void run() { mTextView.setText(text); } }); } } //ThreadFragment public class ThreadFragment extends Fragment { private ThreadRetainWithFragmentActivity mActivity; private MyThread t; private class MyThread extends Thread { @Override public void run() { final String text = getTextFromNetwork(); mActivity.setText(text); } private String getTextFromNetwork() { //네트워크 시뮬레이션 SystemClock.sleep(5000); return "Text from network"; } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); // 자동으로 스레드 유지 } @Override public void onAttatch(Activity activity) { super.onAttatch(activity); mActivity = (ThreadRetainWithFragmentActivity) activity; } @Override public void onDetach() { super.onDetach(); mActivity = null; } public void execute() { t = new MyThread(); t.start(); } }
7.3 마치며
이번시간에는 스레드의 정의 인터럽트 방법, 구성요소 생명 주기에서 스레드 유지 방법에 대해서 알아보았다. 가장 중요한 것은 응용 프로그램 메모리 누수 위험과 크기를 줄이고 스레드의 시작과 종료를 제어하기 위해서 스레드 관리가 필요한 것이다.