1. 작업스레드에서 메인스레드로 작업 전달하기




안드로이드에서 작업스레드는 UI작업을 할 수 없으므로 메인 스레드로 작업을 전달하여 작업스레드에서 UI를 변경하는 것처럼 만들어야 합니다.



그 방법으로는 4가지가 있습니다. 


1. Handler.post()

2. Activity.runOnUiThread()

3. view.post()

4. AsyncTask 클래스



이 4가지의 공통점은 작업스레드가 메인스레드로 메시지를 전달한다는 것 입니다.



메인스레드는 내부적으로 Looper을 가지며 그 안에는 메시지큐가 포함됩니다.



메시지큐는 다른 스레다나 혹은 자기 자신으로부터 전달받은 Message를 기본적으로 선입선출형식으로 보관하는 큐입니다.



Looper는 메시지큐에서 메시지나 Runnable객체를 차례로 꺼내 Handler가 처리하도록 전달합니다. 

Handler는 Looper로 부터 받은 메시지를 실행, 처리, 다른스레드로부터 메시지를 전달받아 메시지큐에 넣는 역할을 하는 스레드간의 통신 장치입니다.












2. 구현하기(Handler.post(),Activity.runOnUiThread())




2.1. Handler.post()


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.example.user.myapplication;
 
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
 
public class MainActivity extends AppCompatActivity {
    Handler handler;                //메인 스레드로 작업을 전달할 핸들러
    TextView myThreadText;          //작업스레드의 이름을 출력할 텍트스뷰
    TextView mainThreadText;        //메인스레드의 이름을 출력할 텍트스뷰
 
    String myThreadStr;             //작업스레드의 이름을 출력할 문자열
    String mainThreadStr;           //메인스레드의 이름을 출력할 문자열
 
    boolean flag;                   //스레드 내부의 while문을 제어할 flag
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);     //레이아웃 연결
 
        myThreadText = (TextView) findViewById(R.id.myThreadText);              //출력할 텍스트뷰 연결
        mainThreadText = (TextView) findViewById(R.id.mainThreadText);          //출력할 텍스트뷰 연결
 
        handler = new Handler();        //메인 스레드로 작업을 전달할 핸들러
 
        myThreadStr = "";
        mainThreadStr = "";
        flag = true;
 
        Thread th = new Thread(new Runnable() {
            @Override
            public void run() {
 
                Thread.currentThread().setName("하릐's thread");      //작업스레드의 이름 변경
 
                while(flag){
                    try {
                        myThreadStr += Thread.currentThread() + "\n";
 
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                //메인스레드가 처리한 작업의 번호
                                mainThreadStr += Thread.currentThread() + "\n";
                                mainThreadText.setText(mainThreadStr);
                                myThreadText.setText(myThreadStr);
 
                            }
                        });
 
                        Thread.sleep(1000);         //스레드 대기 (메인스레드 처리)
 
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                 }
            }
        });
 
        th.start();
    }
}
 
cs


핸들러의 post()를 사용해 작업스레드에서 메인스레드로 작업을 전달하고 있습니다.


36번째 줄 Thread.currentThread().setName("하릐's thread"); 는 작업스레드의 이름을 하릐's thread로 변경합니다.


42-48번째 줄에서 작업스레드의 이름과 post내부에서 스레드의 이름을 호출하면 두개의 스레드의 이름이 출력되는 것을 확인할 수 있습니다.




<결과 화면>






2.2. Activity.runOnUiThread()



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.example.user.myapplication;
 
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
 
public class MainActivity extends AppCompatActivity {
    Handler handler;                //메인 스레드로 작업을 전달할 핸들러
    TextView myThreadText;          //작업스레드의 이름을 출력할 텍트스뷰
    TextView mainThreadText;        //메인스레드의 이름을 출력할 텍트스뷰
 
    String myThreadStr;             //작업스레드의 이름을 출력할 문자열
    String mainThreadStr;           //메인스레드의 이름을 출력할 문자열
 
    boolean flag;                   //스레드 내부의 while문을 제어할 flag
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);     //레이아웃 연결
 
        myThreadText = (TextView) findViewById(R.id.myThreadText);              //출력할 텍스트뷰 연결
        mainThreadText = (TextView) findViewById(R.id.mainThreadText);          //출력할 텍스트뷰 연결
 
        handler = new Handler();        //메인 스레드로 작업을 전달할 핸들러
 
        myThreadStr = "";
        mainThreadStr = "";
        flag = true;
 
        Thread th = new Thread(new Runnable() {
            @Override
            public void run() {
 
                Thread.currentThread().setName("하릐's thread");      //작업스레드의 이름 변경
 
                while(flag){
                    try {
                        myThreadStr += Thread.currentThread() + "\n";
 
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                //메인스레드가 처리한 작업의 번호
                                mainThreadStr += Thread.currentThread() + "\n";
                                mainThreadText.setText(mainThreadStr);
                                myThreadText.setText(myThreadStr);
 
                            }
                        });
 
                        Thread.sleep(1000);         //스레드 대기 (메인스레드 처리)
 
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                 }
            }
        });
 
        th.start();
    }
}
 
cs




runOnUiThread의 사용 방법은 handler.post와 유사합니다.




<결과 화면>






3. Handler.post 와 Activity.runOnUiThread의 차이



https://medium.com/@yossisegev/understanding-activity-runonuithread-e102d388fe93





























+ Recent posts