본문 바로가기

안드로이드

스레드와 핸들러 이해하기

반응형

//정독 필수 

https://junghun0.github.io/2019/06/11/android-handler/

 

[Android] Handler 사용해보기 - Junghoon's Blog

Handler?

Junghun0.github.io

 

안드로이드에서 ui처리할때 사용되는 기본 스레드를 메인스레드라고 부른다.

 

메인스레드에서 이미 ui 에 접근하고 있으므로 새로 생성한 다른 스레드에서는 핸들러 객체를 이용해서 메세지를 전달함으로써 메인스레드에서 처리하도록 만들수 있다.

 

데드락: 동시에 두곳이상에서 요청이 생겼을때 어떤 것을 먼저 처리할지 판단 할 수 없어서 발생하는 시스템상의 문제 

 

=>동시접근으로 발생하는 데드락 문제를 해결하는 가장 간단한 방법은 작업을 순서대로 처리하는 것이지만, 이 역할은 스레드안에서 동작하는 핸들러가 담당합니다.

 

스레드 구현 방법

1.핸들러로 메세지 전송하기 (코드가 복잡해보이는 단점이있다)

2. Runnable 객체 실행하기 

 

<1번으로 해보기!! >

ex) 안되는 예 (thread객체에서 ui객체에 직접 접근한 예) 

 

 

package com.example.samplethread;

import androidx.appcompat.app.AppCompatActivity;

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

public class MainActivity extends AppCompatActivity {

    int value =0;
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView=findViewById(R.id.textView);
        Button button= findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                BackgroundThread thread =new BackgroundThread();
                thread.start();
            }
        });
    }
    class BackgroundThread extends Thread{
        public void run(){
            for(int i=0;i<100;i++){
                try{
                    Thread.sleep(1000);
                }catch (Exception e){}

            }
            value+=1;
            Log.d("Thread","value : "+value);
            textView.setText("value값 : "+value); //스레드 안에서 테스트뷰 메서드 호출하기
                                                 //에러!!  메인스레드에서 관리하는 ui 객체는 내가 직접만든 스레드객체에서는 접근 할수 없다.
        }
    }
}

 

ex ) 올바른예 (내가 만든 쓰레드 객체에서는  핸들러를 이용해서 ui객체에 접근할수 있도록 한다.)

 

 

package com.example.samplethread;

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

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

public class MainActivity extends AppCompatActivity {

    int value =0;
    TextView textView;
    MainHandler handler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView=findViewById(R.id.textView);
        Button button= findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                BackgroundThread thread =new BackgroundThread();
                thread.start();
            }
        });
        handler=new MainHandler();//핸들러는 oncreate 메서드에서 액티비티가 초기화 될때 new연산자를 이용해서 객체로만들어진다.
    }
    class BackgroundThread extends Thread{
        public void run(){
            for(int i=0;i<5;i++){
                try{
                    Thread.sleep(1000);
                }catch (Exception e){}

            }
            value+=1;
            Log.d("Thread","value : "+value);

            Message message= handler.obtainMessage(); //메세지 큐에 넣기
            Bundle bundle=new Bundle();
            bundle.putInt("value",value);
            message.setData(bundle); //메세지 객체에는 bundle 객체가 들어있어서 put,get을 이용해서 메세지 전달하기

            handler.sendMessage(message); //핸들러로 메세지 보내기

        }
    }
    public class MainHandler extends Handler { //이렇게 정의한 핸들러는 oncreate 메서드에서 액티비티가 초기화 될때 new연산자를 이용해서 객체로만들어진다.
        @Override
        public void handleMessage(Message msg) { //핸들러안에서 전달받은 객체 처리하기
            super.handleMessage(msg);


            Bundle bundle=msg.getData();
            textView.setText("Value 값:"+bundle.getInt("value"));
        }
    }

}

 

<2번으로 해보기>

package com.example.samplethread;

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

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

public class MainActivity extends AppCompatActivity {
    int value=0;
    TextView textView;
    Handler handler=new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView=findViewById(R.id.textView);
        Button button= findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                BackgroundThread thread =new BackgroundThread();
                thread.start();
            }
        });

    }
    class BackgroundThread extends Thread{

        public void run(){
            for(int i=0;i<5;i++){
                try{
                    Thread.sleep(1000);
                }catch (Exception e){}

            }
            value+=1;
            Log.d("Thread","value : "+value);
           handler.post(new Runnable(){ //새로 만든  runnable 객체를 핸들러의 post로 전달하면 이 객체에 정의된 run 메소드안의 코드들이 메인스레드에서 실행됨.
               @Override
               public void run() {
                   textView.setText(String.valueOf(value));
               }
           });
        }
    }


}
반응형

'안드로이드' 카테고리의 다른 글

일정시간이후에 실행하기  (0) 2021.02.03
일정시간이후에 실행하기  (0) 2021.02.03
Intent란  (0) 2021.01.27
activity 자동회전  (0) 2021.01.26
[안드로이드] 검색 기능  (0) 2018.01.02