

- inner class 사용 - 하나의 클래스 또는 메소드에서만 사용되는 클래스가 필요할 때 사용
인터페이스 구현하거나 클래스를 상속받아 사용한다 ==> 오버라이딩
package com.example.ex220519;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Button btn_time;
private TextView tv_time;
private int time; //시간 저장변수
private Handler handler = new Handler(){ // Thread 에서 데이터를 넘겨받아 UI/UX 부분을 수정할 수 있게 해주는 객체
@Override
public void handleMessage(@NonNull Message msg) {
// 스레드로부터 데이터를 넘겨받는 메소드
tv_time.setText(msg.arg1+"");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_time = findViewById(R.id.btn_time);
tv_time = findViewById(R.id.tv_time);
btn_time.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//TimeThread timeThread = new TimeThread();
//timeThread.start();
Thread t = new Thread(new InTimeThread()); // 일반 Thread에 익명클래스로
t.start();
}
});
}
public class InTimeThread implements Runnable{
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
time++;
Message message = new Message();
message.arg1 = time;
handler.sendMessage(message);
// 1초에 한번씩 멈추면 time변수에 카운팅
// 1초당 1씩 카운트
//바로 setText 하면 에러남 스레드에서 -> 핸들러에게 메시지 만들어 보내야됨
} catch (InterruptedException e) { //스레드 interrupt 시 예외처리
e.printStackTrace();
}
}
}
}
public class TimeThread extends Thread{
@Override
public void run() {
// Thread를 실행시키는 메소드
while (true) {
try {
Thread.sleep(1000);
time++;
Message message = new Message();
message.arg1 = time;
handler.sendMessage(message);
// 1초에 한번씩 멈추면 time변수에 카운팅
// 1초당 1씩 카운트
//바로 setText 하면 에러남 스레드에서 -> 핸들러에게 메시지 만들어 보내야됨
} catch (InterruptedException e) { //스레드 interrupt 시 예외처리
e.printStackTrace();
}
}
}
}
}

package com.example.ex220519;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity2 extends AppCompatActivity {
private Button btn_start, btn_stop, btn_reset;
private TextView tv_result;
private int minute;
private int second;
private int millisencond;
private boolean onoff = true;
private Handler handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
String result = "";
if(msg.arg1 < 10){
result += "0" + msg.arg1;
}else {
if(msg.arg1 == 100){ //1초가 됐다는 뜻
second++;
millisencond = 0;
}
result += msg.arg1;
}
if(second < 10){
result = "0" + second + "." + result;
} else {
result = second + "." + result;
if (second >= 60){
minute++;
second = 0;
}
}
if(minute < 10) {
result = "0" + minute + ":" + result;
}else {
result = minute + ":" + result;
}
tv_result.setText(result);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
btn_reset = findViewById(R.id.btn_reset);
btn_start = findViewById(R.id.btn_start);
btn_stop = findViewById(R.id.btn_stop);
tv_result = findViewById(R.id.tv_result);
btn_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MyThread thread = new MyThread();
thread.start();
}
});
btn_stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onoff = false;
}
});
btn_reset.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
minute = 0;
second = 0;
millisencond = 0;
tv_result.setText("00:00.00");
}
});
}
public class MyThread extends Thread{
@Override
public void run() {
// Thread를 실행시키는 메소드
onoff = true;
while (onoff) {
try {
Thread.sleep(10);
millisencond++;
Message message = new Message();
message.arg1 = millisencond;
handler.sendMessage(message);
// 1초에 한번씩 멈추면 time 변수에 카운팅
// 1초당 1씩 카운트
//바로 setText 하면 에러남 스레드에서 -> 핸들러에게 메시지 만들어 보내야됨
} catch (InterruptedException e) { //스레드 interrupt 시 예외처리
e.printStackTrace();
}
}
}
}
public class InTimeThread implements Runnable{
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
millisencond++;
Message message = new Message();
message.arg1 = millisencond;
handler.sendMessage(message);
//바로 setText 하면 에러남 스레드에서 -> 핸들러에게 메시지 만들어 보내야됨
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}