안드로이드2015. 2. 1. 12:32

스레드를 반드시 써야 하는 이유는 잠시 살펴봤고 이번에는 실제 스레드를 사용해 보자.

스레드 테스트를 하고자 간단하게 소스를 작성한다. 아래는 소스이다.

package kr.corej.myapplication;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// 간단하게 Thread 생성자만으로 스레드 실행
		new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				firstWork(getApplicationContext());
			}
		}).start();

		SelectThread thread = new SelectThread();
		thread.setDaemon(true);
		thread.start();
	}

	public static void firstWork(Context context) {
		// 일단 작업하고 보자.
	}

	class SelectThread extends Thread {
		public void run() {
			Message msg = handler.obtainMessage();
			// 데이터 조회하는 작업
			msg.arg1 = dataSelection();
			handler.sendMessage(msg);
		}
	}

	private void countdown() {
		for (int j = 0; j < 10; j++) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	int dataSelection() {
		// UI Thread: progress linear
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				// 데이터 처리 중임을 알리는 로딩바를 보여주는 작업
			}
		});

		// 데이터 조회 시간이 10초 정도 걸린다고 치고.
		countdown();

		// ListView 같은 곳에 담을 데이터를 불러와서 담고, 정렬하는 작업
		// 데이터를 불러들일 때 시간이 걸릴 수 있기 때문에 스레드로 처리

		// 조회된 데이터가 10건이라고 가정, 10건을 return
		return 10;
	}

	Handler handler = new Handler(new Handler.Callback() {
		@Override
		public boolean handleMessage(Message msg) {
			// TODO Auto-generated method stub
			// 스레드 작업이 끝나면 실제 레이아웃을 건드리는 작업은 여기서 처리한다. (조회된 건수로 변경하는 작업 포함)

			// 시간이 오래 걸리는 작업이 끝났기 때문에 로딩바도 없애주는 작업

			Toast.makeText(getApplicationContext(), msg.arg1 + "건이 조회되었습니다.",
					Toast.LENGTH_SHORT).show();

			return true;
		}
	});

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();

		// noinspection SimplifiableIfStatement
		if (id == R.id.action_settings) {
			return true;
		}

		return super.onOptionsItemSelected(item);
	}
}

조금씩 떼어서 좀 더 상세히 보자.

		// 간단하게 Thread 생성자만으로 스레드 실행
		new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				firstWork(getApplicationContext());
			}
		}).start();

onCreate 메소드 안에 스레드 생성자이다.

이렇게 간단하게 스레드를 생성해서 사용할 수도 있다. 스레드 뭐 별거 없다.

firstWork 함수 부분에 스레드로 돌릴 작업 내용을 넣으면 된다.

이처럼 간단한 스레드는 작업이 끝난 후에 레이아웃을 변경하거나 당장 화면에 영향을 미치는 작업이 아닐 때 쓸 수 있다.

		SelectThread thread = new SelectThread();
		thread.setDaemon(true);
		thread.start();

이 부분은 Thread를 상속해서 만든 SelectThread 객체 생성과 호출 부분이다.

setDaemon(true) 메소드는 데몬 스레드로 메인 스레드가 종료되면 함께 종료된다.

		// UI Thread: progress linear
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				// 데이터 처리 중임을 알리는 로딩바를 보여주는 작업
			}
		});

dataSelection() 함수 안에 있는 runOnUiThread 역시 스레드인데 UI 변화에 관련된 처리를 담당한다.

(메인 스레드가 아닌) 스레드 실행 중에는 안드로이드 UI를 변경이나 조작할 수 없다.

저 부분은 데이터 처리 중임을 알리는 로딩바를 Visible 시키거나 UI를 조작하는 작업을 한다는 가정인데 언급한 것처럼 dataSelection 함수 자체가 스레드 실행 중에 있으므로 메인 스레드 도움 없이 UI를 변경하면 안 된다.


끝으로 SelectThread 작업이 끝나면 핸들러를 호출해서 마무리한다.

			handler.sendMessage(msg);

핸들러 부분은 핸들러 안 주석으로 상세설명을 대신한다.


코어제이 홈페이지 제작 소개


코어제이 캔디 앱 소개


Posted by 코어제이