본문 바로가기
App/Android Studio

Android Studio - 스레드와 핸들러

by 코젼 2022. 8. 11.
728x90
반응형

2022-08-10(38일차), 11(39일차)



📃핸들러를 사용하지 않고 스레드만 사용할 경우

화면에 마지막 5만 표시된다.

◾ Log에는 모두 찍힘


📝activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn_start"
            android:onClick="onClickStart"
            android:text="시작"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn_stop"
            android:onClick="onClickStop"
            android:text="중지"/>

    </LinearLayout>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:id="@+id/tv_count"
        android:text="0"
        android:layout_centerInParent="true" />

</RelativeLayout>

 


📝MainActivity.java

package com.project.test04;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    TextView tv;
    int count = 0;

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

        tv = (TextView)findViewById(R.id.tv_count);
    }

    public void onClickStart(View v){

        count = 0;
        tv.setText(count + "초");

        for(int i = 0 ; i<5 ; i++){

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            count ++;
            tv.setText("cont : " + count);

            Log.i("jenn", "count : " + count);
        }


    }

    public void onClickStop(View v){

        Toast.makeText(this,
                "중지 버튼을 눌렀습니다. 현재 count는 " + count + "입니다",
                Toast.LENGTH_SHORT).show();
    }
}

💡핸들러

◾ 핸들러는 자신을 생성한 스레드와 그 스레드의 메시지 큐에 바인딩 되어 메시지나 러너블 객체를 전달하고, 메시지 큐로부터 나오는 대로 이를 처리하는 역할의 클래스다.


📃스레드, 핸들러 사용 예제

1초씩 증가하는 것을 실시간으로 확인할 수 있다.


📝activity_main.java

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn_start"
            android:onClick="onClickStart"
            android:text="시작"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn_stop"
            android:onClick="onClickStop"
            android:text="중지"/>

    </LinearLayout>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:id="@+id/tv_count"
        android:text="0"
        android:layout_centerInParent="true" />

</RelativeLayout>

📝MainActivity.java

package com.project.test05;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    TextView tv;
    int count = 0;

    Handler myHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if(msg.what == 1) {
                tv.setText(++count + "초");
                sendEmptyMessageDelayed(1, 1000); // 1초후에 메시지 보내라고 요청한다.
            }
        }
    };

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

        tv = (TextView)findViewById(R.id.tv_count);
    }

    public void onClickStart(View v){

        count = 0;
        tv.setText(count + "초");
        myHandler.sendEmptyMessage(1);// 지연없이 메시지 보내기

        for(int i = 0 ; i<5 ; i++){

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            count ++;
            tv.setText("cont : " + count);

            Log.i("jenn", "count : " + count);
        }


    }

    public void onClickStop(View v){

        Toast.makeText(this,
                "중지 버튼을 눌렀습니다. 현재 count는 " + count + "입니다",
                Toast.LENGTH_SHORT).show();
    }
}

📃핸들러로 깜빡이는 텍스트뷰 만들기


📝activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="잠깨라우"
        android:layout_marginTop="300dp"
        android:layout_gravity="center"
        android:textSize="40dp"
        android:background="#ff9999"
        android:id="@+id/tv"/>
</LinearLayout>

📝MainActivity.java

package com.project.test06;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    Handler myHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            TextView tv = findViewById(R.id.tv);
            if(msg.what == 1) {
                if(tv.getVisibility() == View.VISIBLE) {
                    tv.setVisibility(View.INVISIBLE);
                    sendEmptyMessageDelayed(1, 1000);
                }
                else {
                    tv.setVisibility(View.VISIBLE);
                    sendEmptyMessageDelayed(1, 1000);
                }
            }
        }
    };

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

        myHandler.sendEmptyMessage(1);
    }
}

📃핸들러를 이용하여 랜덤 값 띄우기


📝activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btn_start"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="시작"
            android:textSize="30sp" />

        <Button
            android:id="@+id/btn_stop"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_weight="1"
            android:text="중지"
            android:textSize="30sp" />


    </LinearLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/tv_01"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            android:layout_weight="1"
            android:background="#ff9999"
            android:gravity="center"
            android:textSize="40sp" />

        <TextView
            android:id="@+id/tv_02"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            android:layout_weight="1"
            android:background="#99ff99"
            android:gravity="center"
            android:textSize="40sp" />

        <TextView
            android:id="@+id/tv_03"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            android:layout_weight="1"
            android:background="#9999ff"
            android:gravity="center"
            android:textSize="40sp" />


    </LinearLayout>

</LinearLayout>

📝MainActivity.java

package com.project.test07;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    TextView tv1;
    TextView tv2;
    TextView tv3;

    Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);

            switch (msg.what) {
                case 1:
                    tv1.setText(MainActivity.getRandomNum() + "");
                    sendEmptyMessageDelayed(1, 200);
                    break;
                case 2:
                    tv2.setText(MainActivity.getRandomNum() + "");
                    sendEmptyMessageDelayed(2, 300);
                    break;
                case 3:
                    tv3.setText(MainActivity.getRandomNum() + "");
                    sendEmptyMessageDelayed(3, 500);
                    break;
                case 4:
                    removeMessages(1);
                    removeMessages(2);
                    removeMessages(3);
                    break;
            }
        }
    };

    public static int getRandomNum() {
        int n = (int) (Math.random() * 10) + 1;
        return n;
    }

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

        tv1 = findViewById(R.id.tv_01);
        tv2 = findViewById(R.id.tv_02);
        tv3 = findViewById(R.id.tv_03);

        findViewById(R.id.btn_start).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                handler.sendEmptyMessage(1);
                handler.sendEmptyMessage(2);
                handler.sendEmptyMessage(3);
            }
        });

        findViewById(R.id.btn_stop).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                handler.sendEmptyMessage(4);
            }
        });
    }
}

 


📃버튼 비활성화 하기

◾ 버튼을 비활성화 하지 않으면 버튼을 누를 때마다 숫자가 변하는 속도가 점점 빨라진다.


📝MainActivity.java

package com.project.test07;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    TextView tv1;
    TextView tv2;
    TextView tv3;

    Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);

            switch (msg.what) {
                case 1:
                    tv1.setText(MainActivity.getRandomNum() + "");
                    sendEmptyMessageDelayed(1, 200);
                    break;
                case 2:
                    tv2.setText(MainActivity.getRandomNum() + "");
                    sendEmptyMessageDelayed(2, 300);
                    break;
                case 3:
                    tv3.setText(MainActivity.getRandomNum() + "");
                    sendEmptyMessageDelayed(3, 500);
                    break;
                case 4:
                    removeMessages(1);
                    removeMessages(2);
                    removeMessages(3);
                    break;
            }
        }
    };

    public static int getRandomNum() {
        int n = (int) (Math.random() * 10) + 1;
        return n;
    }

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

        tv1 = findViewById(R.id.tv_01);
        tv2 = findViewById(R.id.tv_02);
        tv3 = findViewById(R.id.tv_03);

        findViewById(R.id.btn_start).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                handler.sendEmptyMessage(1);
                handler.sendEmptyMessage(2);
                handler.sendEmptyMessage(3);

                v.setEnabled(false); // 버튼 비활성화
            }
        });

        findViewById(R.id.btn_stop).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                handler.sendEmptyMessage(4);

                ((Button) findViewById(R.id.btn_start)).setEnabled(true); // 중지 누르면 버튼 다시 활성화화
            }
       });
    }
}

📃프로그레스바


📝activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:layout_marginLeft="100dp"
        android:layout_centerInParent="true"
        android:progress="0" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="start"
        android:layout_below="@id/progressBar"
        android:onClick="onClick"
        android:layout_centerHorizontal="true"/>

</RelativeLayout>

📝MainActivity.java

package com.project.test08;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.ProgressBar;

public class MainActivity extends AppCompatActivity {
    ProgressBar pb;

    Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            if(msg.what == 1) {
                if (pb.getProgress() < pb.getMax()) {
                    pb.setProgress(pb.getProgress()+1);
                    sendEmptyMessageDelayed(1, 50);
                }
            }
        }
    };

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

        pb = (ProgressBar) findViewById(R.id.progressBar);
    }

    public void onClick(View view) {
        pb.setProgress(0);
        handler.sendEmptyMessage(1);
    }
}

💡2022-08-11

📃스레드와 핸들러 예제

◾ 스레드에서 TextView에 직접 접근하는 것은 앱이 죽을 수도 있기 때문에 따로 핸들러를 사용한다.


📝activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="시작"
            android:textSize="20dp"
            android:onClick="onClick"
            android:id="@+id/btn_start"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="중지"
            android:textSize="20dp"
            android:id="@+id/btn_stop"/>
    </LinearLayout>


    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="30sp"
        android:id="@+id/tv"/>




</LinearLayout>

📝MainActivity.java

package com.project.test01;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    int count;
    TextView tv;

    Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            tv.setText(count + "초");
        }
    };

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

        tv = findViewById(R.id.tv);
    }

    public void onClick(View v) {
        count = 0;
        tv.setText(count + "초");

        Thread t = new Thread(){
            @Override
            public void run() { // 스레드 동작 -- run메소드 동작
                for(int i=0; i<5; i++) {
                    try {
                        Thread.sleep(1000);
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count++;
                    handler.sendEmptyMessage(1);
                    Log.i("jyeon", count+"");
                }
            }
        };
        t.start(); // 스레드 동작
    }
}

 

728x90
반응형

댓글