본문 바로가기

컴퓨터학원(복습)(수료)

자바(JAVA)기반 안드로이드 웹&앱 개발 45일차 (스레드, AsyncTask, 서버, 소켓)

코딩에 있는 주석은 강사님이 다신 것을 적어온 것입니다.

마지막 예제는.. 빌드 중에 오류가 난것같아서 지우려고 했는데..

gradle을 지워버려서.. 돌아가지 않습니다..

[일정 시간 후에 실행하기]

1. 웹서버와 같은 원격 서버에 접속한 후 웹페이지를 요청할 때 응답이 늦어지거나 응답이 없으면 앱이 대기하고 있는 상황이 지속되는 문제가 생깁니다. 이런 경우에는 기본적으로 별도의 스레드를 만들어 처리하게 됩니다.

2. 핸들러로 지연 시간을 주었을 때 핸들러로 실행되는 코드는 메시지 큐를 통과하면서 순차적으로 실행되기 때문에 UI 객체들에 영향을 주지 않으면서 지연시간을 두고 실행됩니다.

※ 일정 시간 후에 실행하기 예시

☞ 핸들러는 메시지 큐를 사용하므로 메시지들을 순서대로 처리하지만 메시지를 넣을 때 시간을 지정하면 원하는 시간에 메시지를 처리하게 만들 수 있습니다.

★ public boolean sendMessageAtTime(Message msg, long uptimeMillis)

..☞ 메시지를 보낼 시간을 지정할 수 있습니다.

★ public boolean sendMessageDelayed(Message msg, long delayMillis)

..☞ 메시지가 일정 시간이 지난 후 실행되도록 설정할 수 있습니다.

 

[스레드로 메시지 전송하기]

1. 메인 스레드에서 별도의 스레드로 메시지를 전달하는 방법이 필요할 때가 있습니다. 이를 위해 메인 스레드에서 변수를 선언하고 별도의 스레드가 그 값을 읽어가는 방법을 사용할 수도 있습니다.

2. 하지만 별도의 스레드가 관리하는 동일한 객체를 여러 스레드가 접근할 때는 별도의 스레드 안에 들어있는 메시지 큐를 이용해 순서대로 접근하도록 만들어야 합니다.

3. 핸들러가 처리하는 메시지 큐는 루퍼(Looper)로 처리되는데, 그 과정은 일반적인 이벤트 처리 과정과 유사합니다.

4. 루퍼는 메시지 큐에 들어오는 메시지를 지속적으로 보면사 하나씩 처리하게 됩니다. 메인 스레드는 UI 객체들을 처리하기 위해 메시지 큐와 루퍼를 사용합니다. 그러나 별도의 스레드를 새로 만들었을 때는 루퍼가 없습니다. 따라서 만일 스레드나 다른 스레드에서 메시지 전송방식으로 스레드에 데이터를 전달한 후 순차적으로 작업을 수행하고 싶다면 루퍼를 만든 후 실행해야 합니다.

§ 스레드로 메시지 전송하기 예시

 

[AsyncTask 사용하기]

1. AsyncTask 클래스를 상속하여 새로운 클래스를 만들면 그 안에 스레드를 위한 코드와 UI 접근 코드를 한꺼번에 넣을 수 있습니다. 따라서 스레드로 처리해야 하는 코드를 하나의 AsyncTask 클래스로 정의할 수 있다는 장점이 생깁니다.

2. AsyncTask 에 정의된 주요 메서드

메서드 이름

설명

doInBackground

새로 만든 스레드에서 백그라운드 작업을 수행합니다. execute() 메서드를 호출할 때 사용된 파라미터를 배열로 전달받습니다.

onPreExecute

백그라운드 작업을 수행하기 전에 호출됩니다. 메인 스레드에서 실행되며 초기화 작업에 사용됩니다.

onProgressUpdate

백그라운드 작업의 진행 상태를 표시하기 위해 호출됩니다. 작업 수행 중간중간에 UI 객체에 접근하는 경우에 사용됩니다. 이 메서드가 호출되도록 하려면 백그라운드 작업 중간에 publishProgress() 메서드를 호출해야 합니다.

onPostExeCute

백그라운드 작업이 끝난 후에 호출됩니다. 메인 스레드에서 실행되며 메모리 리소스를 해제하는 등의 작업에 사용됩니다. 백그라운드 작업의 결과는 Result 타입의 파라미터로 전달됩니다.

★ 메소드 실행순서

☞ onPreExecute > doInBackground + (onProgressUpdate) > onPostExecute >

★ 스레드 별 메소드

☞ 메인 스레드에서 실행되는 메소드 : onPreExecute, onProgressUpdate, onPostExecute

☞ 신규 스레드에서 실행되는 메소드 : doInBackground

3. AsyncTask 객체의 cancel() 메소드를 호출하면 작업을 취소할 수 있는데, 이 메서드로 작업을 취소했을 때는 onCancelled() 메소드가 호출됩니다.

4. 작업의 진행 상황을 확인하고 싶을 때는 AsyncTask 객체의 getStatus() 메서드를 사용할 수 있습니다. 이 메서드를 호출했을 때 반환되는 AsyncTask.Status 객체는 상태를 표현하고 있으며 각각의 상태는 PENDING, RUNNING, FINISHED 로 구분됩니다.

☞ PENDING : 작업이 아직 시작되지 않았다.

☞ RUNNING : 실행 중

☞ FINISHED : 종료되었음

※ AsyncTask 사용 예시

 

☞ AsyncTask 클래스는 추상 클래스이므로 새로 정의한 클래스에서 필요한 메서드를 다시 정의하여 사용합니다.

☞ < 자료형 > 은 이 클래스를 상속하면서 재정의할 새로운 클래스의 메서드가 어떤 자료형의 파라미터를 가질 것인지를 알려주는 역할을 합니다.

☞ doInBackground() 메서드에서 중간 중간 진행 상태를 UI에 업데이트하도록 만들기 위해 publishProgress() 메서드를 호출합니다.

 

[스레드로 애니메이션 만들기]

1. 표준 자바에서 게임 등에 사용하는 대부분의 애니메이션 효과는 스레드를 사용하므로 기존의 앱 소스를 안드로이드용으로 포팅하려고 할 때는 이미 만들어두었던 코드와 같은 방식을 사용하는 것이 가장 쉽습니다.

※ 스레드로 애니메이션 만들기 예시

 

☞ 리소스 폴더에 들어있는 이미지들을 로딩할 때는 Resources 객체의 getDrawable() 메서드로 그리기 객체를 가져오는 방법과 BitmapFactory.decodeResource() 메서드를 사용해 이미지 비트맵 객체를 가져오는 방법을 함께 사용할 수 있습니다.

 

[서버에 데이터 요청하고 응답받기]

[네트워크 연결 방식 이해하기]

1. 원격지의 서버를 연결하는 가장 단순한 방식은 클라이언트와 서버가 일대일로 연결하는 ‘2-tier C/S(-Client/Server)’ 방식입니다.

2. 3-tier 연결방식(클라이언트 <-> 응용서버 <-> 데이터서버)을 사용하면 서버를 좀 더 유연하게 구성할 수 있습니다. 또 응용 서버와 데이터 서버로 서버를 구성하면 데이터베이스를 분리할 수 있어 중간에 비즈니스 로직(Business Logc)을 처리하는 응용서버가 좀 더 다양한 역할을 할 수 있다는 장점이 생깁니다.

 

[소켓 사용하기]

1. 네트워킹을 이해하려면 먼저 TCP/IP 수준의 통신 방식을 제공하는 소켓이 무엇인지 알아야 합니다. IP 주소로 목적지 호스트를 찾아내고 포트로 통신 접속점을 찾아내는 소켓 연결은 TCP와 UDP 방식으로 나눌 수 있습니다. 하지만 일반적인 프로그래밍에서는 대부분 TCP 연결을 사용합니다.

 

[HTTP 프로토콜과 소켓]

1. HTTP 프로토콜은 소켓으로 웹 서버에 연결한 후 요청을 전송하고 응답을 받은 다음 연결을 끊습니다. (비연결성 Stateless)

2. 안드로이드 소켓 연결 등을 시도하거나 응답을 받아 처리할 때는 스레드를 사용해야 합니다.(강제사항)

3. 스레드를 사용하면서 UI 를 업데이트하려면 핸들러를 사용해야 합니다.

※ HTTP 프로토콜과 소켓 예시

 

☞ send() 메서드와 startServer() 메서드는 모두 네트워킹 기능을 사용할 것이므로 스레드로 만들어야 합니다. 따라서 버튼을 눌렀을 때 스레드 안에서 동작하게 만드는게 중요합니다.

☞ printClientLog() 와 printServerLog() 메서드 안에서는 핸들러 객체를 사용하고 있으며 Runnable 객체의 run() 메서드 안에서 텍스트 뷰를 접근하고 있습니다. 텍스트 뷰의 appen() 메서드로 전달될 파라미터는 printClientLog() 와 printServerLog() 메서드로 전달되는 파라미터가 그대로 전달되어야 하므로 final 로 정의했습니다.