안드로이드App개발 10.activity데이터송수신 thread

5,616 views
5,377 views

Published on

Published in: Technology
2 Comments
7 Likes
Statistics
Notes
  • But I cannot download, ??
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • The content is good !
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
5,616
On SlideShare
0
From Embeds
0
Number of Embeds
20
Actions
Shares
0
Downloads
281
Comments
2
Likes
7
Embeds 0
No embeds

No notes for slide

안드로이드App개발 10.activity데이터송수신 thread

  1. 1. 안드로이드 App 개발10. Activity 데이터 송수신 &Thread 와 Android Main Thread2013.04컨버전스앱개발팀CopyRight 슈퍼로이드 http://cafe.daum.net/superdroid
  2. 2. Activity 데이터 송수신ⓐ public void startActivity (Intent intent)ⓑ public void startActivityForResult (Intent intent, int requestCode)Activity를 활성화 할때 우리는 활성화 되는 Activity에게 Intent를 이용해서원하는 데이터를 전달할 수 있었다.Activity를 활성화하는 함수전달되는 데이터는 intent 를 이용한다.
  3. 3. ※ Intent 강좌 참조Activity 데이터 송수신명시적 intent 암시적 intent잠깐 배운걸 기억해보자!!!!
  4. 4. Activity 데이터 송수신테스트 코드로 이해해 보자.패키지 구성 AndroidManifest.xml2가지 Activity를 등록하고, A Activity가 B Activity를 호출startActivity()
  5. 5. Activity 데이터 송수신1번 :활성화할 B Class정보를Intent에 넣는다.2번 :B Activity로 전달할데이터를 Extra에 넣는다.전달한 데이터는String형으로"superdroid"라는 것을기억하자.3번 :B Activity를 활성화한다.A acitivty에 대한 소스startActivity()
  6. 6. Activity 데이터 송수신B acitivty에 대한 소스1번 :A가 전달할Intent를 getIntent()라는함수로 참조하게 된다.2번 :A가 Intent Extra로 전달한String을 저장한다.3번 :전달 받은 String을 화면으로출력하기 위해TextView에 받은 String을출력한다.startActivity()
  7. 7. Activity 데이터 송수신 startActivityForResult()1번 :A에서 B로 Intent를 통해 Data를 전달.2번 :B가 종료될때 A로 복귀되는데 이때 B에서 A로 특정 데이터를 전달.
  8. 8. Activity 데이터 송수신 startActivityForResult()1번 :startActivityForResult() 함수를 사용해야 결과를 리턴 받을 수 있다.2번 :A에 대한 데이터를 받기 위해서는 getIntent() 함수를 이용한다.3번 :B에 대한 처리를 완료하고 그 결과를 리턴하기 위해서는 setResult() 함수를 이용해서 전달할 데이터를저장하고 꼭 finish()함수로 Activity를 종료하여야 한다.( finish()함수에서 전달할 데이터를 설정하는 코드가 존재함으로 꼭 finish()함수를 사용해야 한다.)4번 :B로 부터 전달 받은 데이터는 A에서 받기 위해 onActivityResult()함수를 overriding해야 한다.시스템에서는 B로부터 전달받은 데이터를 A에서 구현된 onActivityResult() overriding 콜백함수를호출함으로써 데이타가 인자로 전달한다.
  9. 9. Activity 데이터 송수신 startActivityForResult()테스트 코드로 이해해 보자.패키지 구성 AndroidManifest.xml
  10. 10. Activity 데이터 송수신A acitivty에 대한 소스1번 :활성화할 B Activity의class명과 전달할데이터 myName이라는 Key값으로 "superdroid"라는문자열을 Intent에 담았다.2번 :Intent를 전달하였다.차후 B Activity에서는 전달한"superdroid"값이 정상적으로전달되었는지 확인할 것이다.3번 :B Acitivty의 결과를 전달받기 위해 onActivityResult()함수를 overriding하였다.startActivityForResult()
  11. 11. Activity 데이터 송수신B acitivty에 대한 소스1번:A로 부터 전달받은 Intent를얻어옴.2번 :Intent Extra로 전달한 myNameKey에 해당하는 값이전달되었는지TextView 출력.3번A Activity로 전달한 데이터resultText Key 값의 "superdroidresult" 문자열을Extra로 Intent에 담았다.4번:결과로 전달할 Intent를 설정하고finish()함수를 통해B Activity를 종료시킴과 동시에결과로 Intent를 전달하였다.startActivityForResult()
  12. 12. Activity 데이터 송수신 startActivityForResult()결과
  13. 13. Activity 데이터 송수신- RESULT_OK = 0- RESULT_CANCELED = -1- RESULT_FIRST_USER = 11번에서 전달할 Data를 설정하였고, B Activity에 전달할 요청코드를 설정하였다.2번에서 전달한 Data를 수신하였고 그에 대한 처리를 할것이다.3번에서 A Activity에 전달할 결과를 결과 코드와 함께Data(intent)를 전달한다.그 결과는 4번 A Activity에 onActivityResult() 가 호출되면서인자로 전달 된다.startActivityForResult()
  14. 14. Activity 데이터 송수신요청 코드가 왜 필요한가?그 이유는A Acitivity는 꼭 B Activity의 결과만 받지 않기 때문이다.예를 들어 A Activity는 어떤 패키지의 C Activity의 결과도 받을 수 있고,D,E...등등 다른 Activity의 결과도 받을 수 있다.그러나 A Activity의 결과를 받은 함수는 onActivityResult() 함수 하나 밖에 없다.각기 다른 Activity에서 결과를 받은 것을 구분하기 위해서는당연히 요청 코드가 꼭 필요한 것이다.startActivityForResult()
  15. 15. Intent의 Flag 중 Activity간에 데이터를 전달하는 추가 기능Activity 데이터 송수신Intent의 flag 중의 FLAG_ACTIVITY_FORWARD_RESULTA-2는 A-1에게 결과를 전달해야 한다.A-2의 책임을 다른 Activity로 넘기기 위해서A-3를 활성화 하고 Intent Flag로 FLAG_ACTIVITY_FORWARD_RESULT 를 설정하면 된다.A-2는 해당 Flag를 셋팅하고 자신의 할일이 끝났으므로 finish()를 호출하여 종료해 버리면책임은 끝난다.그러므로 A-3가 전달할 Intent를 작성하고 setResult()와 finish()를 호출해 주면 된다.startActivityForResult()
  16. 16. A -> B -> C 순으로 Activity를 활성하고 C가 종료되면서 A로 결과가 전달되는지확인하는 테스트Activity 데이터 송수신Intent의 flag 중의 FLAG_ACTIVITY_FORWARD_RESULTA acitivty에 대한 소스1번 :startActivityForResult() 함수로 B Activity를 활성화2번 :그 결과를 전달 받기 위해onActivityResult() 함수를overriding3번 :Toast로 출력startActivityForResult()
  17. 17. Activity 데이터 송수신Intent의 flag 중의 FLAG_ACTIVITY_FORWARD_RESULTB acitivty에 대한 소스1번 :C Activity를 활성화하고책임을 넘기기 위한FLAG_ACTIVITY_FORWARD_RESULTFlag만 셋팅해 준다.2번 :종료startActivityForResult()
  18. 18. Activity 데이터 송수신Intent의 flag 중의 FLAG_ACTIVITY_FORWARD_RESULTC acitivty에 대한 소스1번 :전달할 Intent를 작성하고setResult()함수를 통해Intent를 설정.2번 :종료를 통해 A로 결과intent를 전달한다.전달할 데이터는 returnText라는 Key 값으로 "superdroid"문자열startActivityForResult()
  19. 19. 결과Activity 데이터 송수신Intent의 flag 중의 FLAG_ACTIVITY_FORWARD_RESULTstartActivityForResult()
  20. 20. Activity 데이터 송수신 startActivityForResult()예외상황/제약사항첫번째 : Activity의 결과를 설정하는 setResult()와 finish()는Activity의 종료되는 과정의 생명주기에 사용될 수 있을까?종료되는 생명주기에 해당 소스를 넣으면 Activity가 종료될때 무조건 호출되니 편할것도 같다.그렇지만, 절대 허용하지 않는다.꼭 finish() 함수를 사용해야 결과가전달되며, 종료 생명주기에서는이미 finish()를 사용해도 무시한다.그러므로 생명주기에서 해당코드를 사용해서는 안되고,특정 이벤트(종료 버튼 click)등에서 사용하도록 하자.
  21. 21. Activity 데이터 송수신 startActivityForResult()예외상황/제약사항두번째 : Intent로 전달하는 데이터 크기는 제한이 없을까?전에 한번 설명한 적이 있다. Intent는 내부적으로 Binder통신을 한다.이렇게 Binder통신은 메모리가 제한적이다.1M 가까이 밖에 쓸 수없다.하지만, 안드로이드에서는 100KB 이상을 사용하지 않도록 공고한다.쉽게 생각하여, 일반적인 자료형은 전달하되...절대 Raw 데이터를 전달하지 않도록 한다.Raw 데이터라고 함은 Image데이터, 동영상 데이터, 아주 긴 Text 데이터 등을 들 수있겠다.
  22. 22. Activity 데이터 송수신 startActivityForResult()예외상황/제약사항세번째 : 모든 경우 Activity의 결과를 전달 받을 수 있을까?배운 Task를 기억하자. 하나의 Task 내에서 결과 전달은 모두 가능하다.다른 Task에서 결과 전달은 불가능 하다.기술적으로 말하자면Root Acitivty는 결과를 전달할 수 없다.Task에서 배웠던launchMode="singleInstance" 속성singleTask…FLAG_ACTIVITY_NEW_TASK... 등
  23. 23. Activity 데이터 송수신 startActivityForResult()예외상황/제약사항마지막으로 네번째 : 최초 전달 받은 Intent가 변경되는 경우는 없는가?조금 어려운 말일 수 있다.이 말을 이해하려면 Task에서 배웠던 Activity재사용에 대해서 이해하여야 한다.- launchMode = "singleInstance"- launchMode = "singleTask"- launchMode = "singleTop" orFALG_ACTIVITY_SINGLE_TOP위와 같이 설정된 경우 Activity를재사용하게 될 수 있다고 했었다.
  24. 24. Activity 데이터 송수신 startActivityForResult()예외상황/제약사항
  25. 25. Activity 데이터 송수신 startActivityForResult()예외상황/제약사항Activity가 최초 활성화 될때 받은 Intent는 다시 재사용되어도없어지지 않는다.다시 말하자면 새로운 Intent가 와서 아무리 getIntent()를 해도 최초에 받은 Intent 만유지 된다는 것이다.그렇다면 재사용 시 전달되는 새로운 Intent는 참조할 방법이 없을까?onNewIntent()라는 함수를 Overriding하면 가능하다.onNewIntent() 함수는 이와 같이 새로운 Intent가 전달되면 호출된다.다시 말하면 해당 Activity가 재사용되어 활성화 되면 호출된다는 것이다.새로운 Intent정보는 onNewIntent()함수의 인자로 전달됨을 기억하자.onRestart() -> on Start() -> onResume() 함수가 순서대로 생명주기에서 호출된다.onNewIntent() 함수는 생명주기 함수가 호출되기전 제일먼저 호출 됨으로써여러가지 예외처리를 할 수 있도록 한다.
  26. 26. Thread 와 Android Main Thread1. Thread 의 필요성하나의 Process에서는 하나의 Thread가 기본적으로 동작한다.즉 Thread는 하나의 일을 처리하는 job 단위라고도 볼 수 있다.
  27. 27. Thread 와 Android Main Thread1. Thread 의 필요성동시에 여러 가지 작업을 해야 하는 경우하나의 Thread로 처리하기 힘들다.네트워크에서 파일을 다운로드 함과 동시에화면에 다운로드 받는 양을 표시하고자 하는경우 두 가지의 Thread가 필요한 것이다.또 추가적으로 한 Process에서는 모든Memory를 공유할 수 있다.Thread 또한 Process안에 포함되었으므로모든 객체(메모리)를 접근할 수 있다.이 것을 Thread의 최고의 강점이라고 할 수도있고,Thread를 복잡하다고 생각하게 하는부분이기도 하다.복잡하다는 이유는 여러 Thread는 비동기적으로 동시에 돌고 있는 상태에서서로 특정 참조 변수를 변경하고 참조 하면,해당 변수의 유효성을 보장받지 못하기때문이다.
  28. 28. Thread 와 Android Main Thread2. Android의 Main Thread하나의 Process는기본적으로 최소 하나의Thread가 존재한다고하였다.android 패키지는 해당Thread의 용도를 UIThread로 활용을 하고있다.다른 Thread를 생성하여UI 작업을 하는 것을허용하지 않는다.UI 작업처리를 하는Thread를 MainThread라고도 한다.
  29. 29. Thread 와 Android Main Thread2. Android의 Main Thread여러 Thread에서 그림을 그릴수 있다고 정하고,Thread 1에서는 배경을 그리고,Thread 2에서는 태양을 그리고,Thread 3에서는 산을 그린다.그리는 순서는 꼿 1,2,3 번 순서로 그려야 한다.1번과 2번 과정에서 그렸던 그림이 3번의그림으로 인해 덮어 버린다.이 것을 UI가 꼬였다고들 한다.다른 Thread를 생성하여 UI 작업을 하는 것을 허용하지 않는다.
  30. 30. Thread 와 Android Main Thread2. Android의 Main Thread그렇다면 정말 Main Thread가 아닌곳에서 화면에 그리는 작업을 할 수 없을까?정답은 그렇다.하지만 다른 Thread에서 Main Thread가 그림을 그리도록 요청할 수 있다.Main Thread는 구조적으로 그러한 것을 지원한다.그것을 HandlerThread 라고 부르고Main Thread는 HandlerThread구조이다.HandlerThread는 내부적으로Queue를 가진다.그 Queue안에는 처리 해야 하는일을 해당 Thread에서나 혹은다른 Thread에서 넣을 수 있다.그러므로 다른 Thread에서그리는 작업을 시키기 위해HandlerThread의Queue에 Job를 넣을 수 있는것이다.2.1. Handler Thread
  31. 31. Thread 와 Android Main Thread2. Android의 Main Thread Queue에Message를 집어넣는 역할을 한다.1~8번의 HandlerClass의 함수를사용하여 Queue에메시지를 넣게 된다.참고로 메시지에는메시지가 처리해야할 시간을 설정할수도 있다.그 것이 바로4,5,7,8번 함수에들어가는uptimeMillis와delayMillis 이다.uptimeMillis 는실행될 절대적시간이며,delayMillis는 현재시간을 기준으로해당 시간이후에실행된다는의미이다.Handler2.1. Handler Thread
  32. 32. Thread 와 Android Main Thread2. Android의 Main Thread첫번째는 두 가지 정보를설정함으로써 가능하다.when이라는 변수를 통해자신이 실행되는 시점의시간을 설정할 수 있다.실행되어야 할 시간이되면 실행되는 코드가바로 callback이다.callback는Runnable이다.Runnable은Interface이며, 내부에구현해야할 함수는run()이다.즉 run()함수를Message객체를생성할때 구현해 주면looper가 실행해 주는것이다.Message가 처리되는 방법 12.1. Handler Thread
  33. 33. Thread 와 Android Main Thread2. Android의 Main ThreadMessage가 처리되는 방법 27가지 값이 사용된다.when 변수는 위에서 설명하였다.target은 Handler이다.Handler는 Queue에 Message를 넣어주는 객체라고하였다.그 밖에 기능으로 Handler를 생성할때 위와 같이public void handleMessage() 함수를 overriding 하여구현해 줄 수 있다.첫번째 방법에서 callback 즉 Runnable 객체의 run()을구현해 주고 실행이 되었다.두번째 방법은 바로 handleMessage() 함수를 구현하여실행하게 되는 것이다.what는 handleMessage에서 작업을 구분할 명이다.위의 예제는 "0"이라고 하였지만 당연히 구현시에는"static int DRAW_RECT = 0" 과 같이정의 하여 사용해야 한다.arg1, arg2, obj, data 등은 handleMessage함수로전달할 데이터 들이다.arg1, arg2는 int 형이므로 정수 데이터를 쉽게 전달할것이고obj는 Object 형이므로 여러가지 객체를 전달할 것이다.data는 Bundle 형이므로 여러가지 데이터 덩어리를넣어서 전달할 수 있다.2.1. Handler Thread
  34. 34. Thread 와 Android Main Thread2. Android의 Main Thread전체적으로 처리되는 과정2.1. Handler Thread
  35. 35. 1번에서 HandleThread를 생성하면,2,3,4 번과 같이 MessageQueue가 생성되고, Looper가 생성되고 결국 HandlerThread가 생성이 될 것이다.5번에서 해당 Thread를 실행하기 위해 HandlerThread를 start하게 되면6번과 같이 Thread의 run()이 실행되고7번과 같이 Looper가 계속 반복하여 MessageQueue에 메시지를 꺼내가려고 할 것이다.(Message가 없으면 잠시 wait하게 된다.)8번에서 Handler를 생성하면9번과 같이 MessageQueue에 메시지를 넣기 위하여Handler는 Looper를 참조하게 된다.(Looper는 MessageQueue를 참조하므로 결국 메시지를 넣을 수 있는 참조가 된다.)10번에서 처리해야할 Job 단위인 Message를 하나 생성한뒤처리해야할 코드를 넣어준다.코드를 넣는 방법은 위에서 두가지라고 했다.(callback : Runnable 객체의 run()을 구현해서 넣는 방법과,target : Handler의 handleMessage()를 구현하는 방법이 있다.)두가지 방법을 모두 넣게 되면 callback이 실행된다.11번에서 Handle.sendMessage()함수 등을 이용해서MessageQueue에 메시지를 넣으면12번에서 Looper가 넣은 메시지를 하나꺼내서13번과 같이 callback이 구현되어 있으면 callback의 run()함수를 실행해 주고target이 구현되어 있으면 target의 handleMessage()함수를 실행해 준다.이 것이 전체적인 구조이며, MainThread는 위와 같은 구조를 가진다.Thread 와 Android Main Thread2. Android의 Main Thread전체적으로 처리되는 과정2.1. Handler Thread
  36. 36. Thread 와 Android Main Thread2. Android의 Main Thread다른 Thread에서 화면 그려보기 예 11번에서 Main Thread의 MessageQueue에Message를 넣기 위해Handler 객체를 하나 생성한다.2번에서 버튼이 클릭되었을때 Thread 객체를하나 만든다.3번에서 Runnable 객체를 하나 생성과동시에 실행될 내용을 담을 run() 함수를구현한다.그 내용은 화면에 "Count : 50" 이라고 그림는작업이다.4번에서 Message 객체를 생성하고 객체 내에runnable 객체를 참조시키기 위해 Message생성자에 넣어준다.5번에서 MessageQueue에 Message를넣는다.1. callback : Runnable객체의 run()을 구현해서 넣는 방법
  37. 37. Thread 와 Android Main Thread2. Android의 Main Thread다른 Thread에서 화면 그려보기 예 21번에서 Handler 객체를 생성과 동시에처리할 내용을 담을 handleMessage() 함수를구현해 준다.2번에서 화면에 그리는 작업 요청(msg.what)이 오면 화면에 그리는 코드를 작성한다.3번에서 버튼이 클릭되면 Thread를 하나생성한다.4번에서 Message를 하나 생성한다. 여기서Message.obtain() 함수의 두번째 인자가msg.what에 해당하고 요청 코드에 해당한다.작성된 메시지를 MessageQueue에 넣는다.2. target : Handler의handleMessage()를 구현하는 방법
  38. 38. Thread 와 Android Main Thread2. Android의 Main Thread자 그렇다면 왜 이렇게 두가지 방법을 제공할까?Runnable 객체의 run()를 구현하는 방법은 간단히 한가지 일을 처리할 때많이 사용한다.소스를 보면 알겠지만 매우 간단하다.Handler 객체의 handleMessage()를 구현하는 방법은한 가지 요청이 아니라 여러 가지 요청을 처리할 때 사용한다.handleMessage()에 다양한 요청(msg.what)에 대한 코드를 미리 구성하고특정 요청이 필요할 때 간단히 Message를 하나 만들어서Handler.sendMessage()함수를 호출하면 된다.
  39. 39. Thread 와 Android Main Thread2. Android의 Main Thread2.2. AsyncTask일단 AsyncTask 객체를 상속받아내부를 구현하고AsyncTask.execute() 함수를 실행하면원하는 동작이 시작된다.1번의 경우는 화면에 진행바의 초기모습을 그린다. (onPrepareExecute()콜백함수를 구현)2번에서는 파일을다운로드한다. (doInBackground()함수 구현)다운로드 받을 파일일 여러개인 경우반복적으로 반복문을 돌면서처리한다.만일 파일하나를 다운받고 화면에진행정도를 그리고자 한다면publishProgress()함수를 호출하면5번과 이 onProgressUpdate()함수가호출된다.우리는 이곳에서 현재 진행정도를화면에 그리면 된다.(onProgressUpdate() 함수구현)6번과 같이 doInBackground()함수의처리가 끝나고 그 결과를 리턴하면7번과 같이 onPostExecute()함수가호출된다. (onPostExecute() 콜백함수구현) 이 곳에서 진행화면을 종료관련화면이든 완료 결과 화면이든 그리면되는 것이다.
  40. 40. Thread 와 Android Main Thread2. Android의 Main Thread2.2. AsyncTaskAsyncTask의 동작을취소하고자 한다면간단히AsyncTask.cancel() 함수를 호출.syncTask를 제어하는함수(execute(), cancel()..)등은꼭 Main Thread에서제어해야 하고, 한번이상 함수를 호출하면안된다.
  41. 41. Thread 와 Android Main Thread2. Android의 Main Thread2.2. AsyncTask여러 가지 파일을다운로드 한다고가정하자.예제
  42. 42. Thread 와 Android Main Thread2. Android의 Main Thread2.2. AsyncTask화면에 다운로드의 진행정도를 표시하는 TextView
  43. 43. Thread 와 Android Main Thread2. Android의 Main Thread2.2. AsyncTask1번에서 구현된 AsyncTask를 상속받은DownloadTask를 하나 생성하였다.이어서 execute()함수를 호출하면서 해당AsyncTask는 동작하게 된다.2번은 AsyncTask를 상속받은 DownloadTask의 구현 내용이다.3번에서 파일의 개수 만큼 반복하면서 파일을다운로드한다. 위에서 말했지만 해당 함수는별도의 Thread에서 동작한다. 그러므로 UI작업을 하지 않는다.중간 중간에 진행정도를 표시하기 위해publishProgress()함수를 호출해 준다.4번은 초기 화면을 그린다.5번은 3번에서 publishProgress()함수가 호출할때마다 호출되는 함수이며, 진행 정도를 화면에갱신한다.6번은 3번의 처리가 끝나서 리턴 되면호출되며,진행완료 결과에 대한 그림을 화면에 그리게되는 것이다.
  44. 44. Thread 와 Android Main Thread2. Android의 Main Thread2.2. AsyncTask1 들을 보자.먼저 첫 번째 인자(빨간1)는AsyncTask를 활성화하는 execute()함수의인자로 들어간다.대부분 처리해야 할 목록을 전달하는 용도로사용된다.두번째 인자(파랑1)는진행과정의 정보를 전달하는 용도로 사용된다.이 정보를 보고 대부분 진행정도를 화면에그리게 된다.세번째 인자(초록1)는doInBackground의 결과즉, 진행하고자 하는 작업의 결과값이다.이 값은 화면에 최종적으로 그려지는 함수onPostExecute() 인자로전달되고 성공, 실패 등의 결과를 화면에출력하게 된다.

×