2013년 8월 30일 금요일

More Joel on Software, 조엘 온 소프트웨어를 넘어서

이전 블로그에서 이전 함 (원본 글 2013/08/30 작성)


 
 모어 조엘 온 소프트웨어 More Joel on Software
 조엘 온 소프트웨어를 넘어서 

조엘 스폴스키 저/이해일 역 | 지앤선(志&嬋)
  

사실 Joel on Software 블로그를 열심히 들여다 본건 아니고 블로그가 좀 유명해지고 보려고 했으나 죄다 영어라서 보기가 싫었고 국내에서 '조엘 온 소프트웨어' 책이 발간되고 나서 봤었다.
그 당시만 해도 웹상에서 소프트웨서 개발에 대한 내용에 대해서 소개하거나 설명, 비판하는 블로그가 많이 없었고 조엘 아저씨가 쓰는 어휘라던지 위트, MS를 가는게 좀 재밌기도 해서 열심히 읽었고 조금이나마 소프트웨어 개발 문화, 역량에 대해서 생각할 수 있었던 것 같다.

암튼 이번 주 도서관에 갔더니 새로운 책이 있어서 빌려 봤었고 그 중 동의하거나 TODO들을 정리함.
책의 전반부에서는 프로그래머에 대해서 프로그래머의 소양에 대한 포스트를 정리 하여 많이 공감되는 부분이 있었으나 후반부에서는 소프트웨어 사업에 대해서 정리를 하여 스타트업을 현재를 별로 고려하고 있지 않은 나에게는 약간 따분했다. 
그리고 사실 조엘 아저씨의 능력과 출신 history 때문인지 나의 생각과는 많고 우리나라 여건과 다소 다른 부분이 있어 그건 그냥 그런 의견도 있구나 라는 생각을 하고 넘겨 버린 것도 있음.

- "제 보고 라인에 선 모든 사람들이 사돈의 팔촌까지 데리고 BillG 검토회에 차석했습니다. 우리 팀 F-카운터도 참석했습니다. 빌이 몇번이나 F로 시작하는 단어를 내뱉는지 세는 게 주요 업무죠."

 : 사실 상사가 욕하는 것은 우리나라 조직 문화에서만 가능한 거라고 생각을 하고 있었던 관계로 의아하면서 웃기긴 했으나 한편으로는 S/W 개발에 대한 냉소적인 생각이 들었음.


- 셋. 개발자를 대하는 실전 지침서

 : 프로그래머를 위한 최고의 근무환경, 개발 장비 제공, 적절한 처우(대우, 직무, 일체감)를 제공해 준다면 최고의 프로그래머가 모일 것이라고 얘기를 하고 있고 뒤쪽 장에서는 수익으로 연결 된다는 얘기를 하고 있음. (사실 21장이 잘 이해는 안되지만...)
 : 심하게 공감가는 글이며 의자, 추가 모니터 같은 개발에 필요한 장비들은 근무기간을 생각하면 금액이 과분한것도 아니고 생산성에 큰 도움이 되지만 S/W 개발에 대해서 문외한인 manager 나 사사건건 계산기 들이미는 사람이 있는 회사 문화에서는 택도 없는 소리임을 알기에 좀 슬픔.
 : 관리방법에 대해서 "명령과 통제 관리방법", "ECON 101 관리방법", "일체감 관리방법" 을 소개하는데 외국에서도 군대식 통재가 있는 것과 가족같은 분위기를 만들어 일체감과 소속감을 만드는 방법이 있음에 좀 놀라웠다. 조엘이 징집, 가족주의가 있는 이스라엘 출신 미국인이라서 그런가?


- 열. 전산학과 학부생에게 건네는 충고

  1. 졸업 전에 글쓰기를 배우세요.
 2. 졸업 전에 C를 배우세요.
 3. 졸업 전에 미시경제학을 배우세요.
 4. 지루하다고 전산학이 아닌 과목을 우습게 여기지 마세요.
 5. 프로그래밍 심화 과정을 수강하세요.
 6. 모든 일자리가 인도로 가버리다는 걱정은 그만하세요.
 7. 무엇을 하든, 훌륭한 회사에서 인턴을 체험하세요.

 : 동의한다, 프로그래머라면 개발 역량은 기본으로 갖춰야 하는데 이를 완성하는 것은 이론 + 코딩 실력 인것 같다. 사실 대학교에서 책으로 배우는 이론 같은 것은 뜬 구름 잡는 얘기 같지만 나중에 실무에서 다... 필요하다. 다른 분야의 지식도 마찬가지.. 뭐 잡스도 연설을 통해 강조 했었으니...
 : 우리나라에서의 인턴은 방학때 대학생들 뽑아서 삽질 시키는 거라 7번은 아직 우리나라 기업환경에서는 역량 개발 보다는 취업을 위해서라면 맞을 듯.


(TODO) Dreaming In CODE 읽어 보기 


- 스물. 증거 기반 일정 세우기

 1. 그 일을 할 개발자만이 제대로 예측할 수 있습니다.
 2. 버그를 발견하면 즉시 바로잡고, 디버깅에 걸린 시간을 원래 소요 시간에 반영하세요.
 3. 초기 예측 시간을 줄이라고 관리자가 개발자를 집적대지 못하게 하세요.
 4. 일정은 장난감 블록 상자입니다.

 : 요즘은 스크럼 방법론을 통해 스프린트를 반복 수행하다 보면 스크럼 팀의 개발 역량이 수렴되어 어느정도 예측이 가능한 것 같음. 하지만 일정은 개발자 본인 혹은 동료 개발자가 잘 아는 것 같고 적절히 기존 스프린트 burndown rate를 기반하여 판단하는게 필요. 또한 잡다한 일들이 중간에 발생하면 바로 스프린트 backlog에 추가 반영하는 것 반드시 필요..


- 스물 여섯. 고음 내기
  "세계 최고 제품은 단지 '생산성 10배' 문제가 아닙니다. '그럭저럭 생산성을 내는' 개발자는 결코 위대한 소프트웨어를 만들어내는 높은 음을 내지 못합니다." ... "2등이 되거나 '충분히 좋은' 제품이나 만들 여유가 없습니다."
  : 좀 씁쓸 하지만 맞는 얘기인걸.. 항상 생각하며 노력 필요.


- 스물 일곱. 생체공학 사무실
 . 문이 닫히는 개인 사무실은 반드시 필요합니다.
 . 프로그래머들에게 전원 콘센트를 많이 제공해야 합니다.
 . 데이터선은 절대 벽을 뜯지 않고 쉽게 재배선할 수 있어야 합니다.
 . 짝 프로그래밍을 할 수 있어야 합니다.
 . 하루 종일 모니터를 보고 일하기 때문에, 먼산을 바라보며 눈을 쉴 수 있어야 합니다.
 . 사무실은 편안한 은신처가 되어야 합니다.

 : 개인 사무실은 꿈이라도 생각해도 짝 프로그래밍, 밖이 보이는 공간.. 효율성을 극대화 한 빌딩 내 닭장 사무실에서 개발 하는 것은 정말 불편하다.


- 스물아홉반. 우아함 
 : 읽어봐야 하나? ==> http://www.alaindebotton.com/architecture.asp

2013년 8월 16일 금요일

Android상에서 Bitmap 처리 관련 링크들 및 Out Of Memory에 대한 개인적인 방안

이전 블로그에서 이전 함 (원본 글 2013/08/16 작성)

Android 상에서 bitmap 처리 관련해서 정리

아래 링크만 참고하세요..
[Android 앱 메모리 최적화]
: (추가) Naver 개발자가 작성한 내용으로 안드로이드 메모리 관련해서 총정리 되어 있습니다.
http://helloworld.naver.com/helloworld/539525

아님 그냥 image loading library 쓰세요..




자바라고 GC 밑고 생각 없이 짜다간 정말 고생할듯....
아니.. 지금 OOM때문에 고생 중이다. 안드로이드 개발 시 ImageView 사용하면
무조건 맞닥드릴 문제인것 같다. 근데 좀 이상한건 관련 패턴 같은게 없다.
사실 나도 지금 정리중이지만 해결이 안되는 leak들이 있음.

일단 개인적인 방안으로는 

- Bitmap을 관리하는 class를 만들어 생성 한 뒤 caching하여 사용하고 메모리 부족 시 스케줄링 방법에 따라서 bitmap recycle을 하는 방법을 사용함.

- 각 activity, fragment에서는 onDestory(), onDetach()에서는 기분째즈님의 "안드로이드 메모리 누수 줄이기"에서 소개한 recursive하게 rootview의 widget을 모두 초기화 함.
 : 하지만 재미 있는 것은 rootview의 widget들을 null 초기화 하고 adapter의 view의 bitmap도 null 초기화 하지만 bitmap reference가 살아 있는게 보인다. 일단 위의 방법을 사용해서 bitmap을 강제로 recycle하므로 문제는 없을 듯.

- context, UI 관련된 widget 참조를 WeakReference를 사용하여 참조하게 함.


[Displaying Bitmaps Efficiently]
: Bitmap 관련된 기본적인 작업들에 대해서 설명.. 뭐 기본이겠다..

[ImageView Bitmap 처리 관련 게시물]

[Bitmap과 힙메모리에 대한 소고..]
: EastGem님이 여러모로 실험을 해서 나온 결과를 정리해 놓았음.

실험 1에서  EastGem님께서 아래와 같은 내용을 말해주고 있었음.
 실험1.
자 요렇게 자료형태를 구성했다.

1. Main 에서 View1, View2 로 참조시켜도 둘다 표현이 된다.
2. 셋중 어느 한군데서 recycle() 을 호출하면 모두 표현불가능해진다. ( invalidtate() 를 호출하기 전에는 표시되어있던건 그냥 있다 )
3. View 로 참조후 Main 에서 bitmap = null 을 줘도 View에서 사용하는데 아무 지장이 없다.
4. View 에서 참조후 한군데서 null 을 줘도 다른 View 나 메인에서는 아무 이상이 없다. 다른 View 로 다시 참조도 가능하다.
5. 두개의 이미지를 번갈아 수십 수백번 하나의 bitmap 참조에 할당해도 문제가 없다.

결론.
Bitmap 클래스는 비트맵의 메모리상의 위치와 크기, 밀도, 등의 각종 정모만 가질뿐.. 실제 Bitmap 의 내용을 변수로 갖지 않는다. 메모리상에서 참조해야할 위치만 가지고 있다고 생각된다. recycle 을 하면 메모리는 해제되지만 getWidth(), getDensity() 같은걸 해보면 정보는 다 그대로 가지고 있다. 메모리를 해제해도 invalidate()를 호출하기 전에 화면이 그대로 있으니 비디오 장치는 따로있다는 말이렸다.
메인에서는 View 로 생성한 Bitmap 을 넘긴후 즉시 null 처리해 버려도 전혀 문제가 되지 않는다.

=> 그래서 일단 App에서 사용하는 Bitmap들은 한곳을 통해 생성하고 관리해도 좋을 것 같다는 생각이 들어 아래와 같은 class 생성
 - Bitmap을 생성해주고 이를 cache하여 같은 resource(bitmap)을 요구할 경우 기존 생성된 cache를 전달
 - Bitmap 생성 시 OOM이 발생할 경우 cache를 스케줄링 방식에 따라 recycle.

 그래서 상위 class를 통해서 모든 bitmap을 생성 및 관리하고 생성된 bitmap을 참고하는 view에서는 단지 null 만 함..


[안드로이드 메모리 누수 줄이기]
: viewgroup의 widget들을 null 처리하거나 adapter에서 메모리 해제를 위한 방법 제공

Root view의 모든 widget들을 recursive하게 참조를 제거해 주는 방법은 괜찮다. 일단 각 activity에서 destory될 때 해당 함수 호출 하여 view와 관련된 resource를 제거 하게 함.


[Android 개발가이드 - Bitmap.recycle()은 가급적 호출해 주는 편이 좋다. (Android 2.x 버전)]
[출처] 아래 링크, 작성자 코드멍키
: 좀 이전 버전인데 맞는지는 모르겠다. 2013년 1월에 업데이트 되어 있는 comment에 의하면 단지 bitmap = null 로도 자원 반환이 가능하다는 의견.

[Points to consider for recycling Bitmap of ImageView] 

bitmap을 제거하는 방법은 recycle() & null 대입을 통한 reference 제거....

[Bitmap OutOfMemoryError]
: Bitmap OutOfMemoryError를 피하기 위한 방법들 소개

[bitmap decode한 결과물 recycle 하는 방법]
: decode한 이후 createBitmap의 결과가 같을 수도 있어 recycle을 하지 않아야할 경우가 있어 hashcode를 비교 필요.

[ImageView의 bitmap recycle]
: 헐.. 이렇게 해도 문제 없나? view가 완전히 destory 되지 않는 경우 "cannot draw recycled bitmaps" exception 발생 가능

2013년 8월 12일 월요일

asmack(smack android library) 사용 시 참고 사항들

이전 블로그에서 이전 함 (원본 글 2013/08/12 작성)

asmack을 사용하다 생긴 사소한 사항들을 정리


[reconnect 상황에서 null pointer exception 발생 현상]

= 증상 설명
# precondition
  : XMPP connection이 기타 사유(network connection close, 동일 id로 타 deivce에서 login 등)으로 close 됨
  : MUC(Multi User Chat) extension을 사용함.

 - XMPP connection을 재 생성하고자 connect를 할 경우 아래와 같이 NullPointerException이 발생

08-12 18:57:36.783: W/System.err(598): java.lang.NullPointerException
08-12 18:57:36.783: W/System.err(598):  at org.jivesoftware.smackx.muc.MultiUserChat$1.connectionCreated(MultiUserChat.java:115)
08-12 18:57:36.783: W/System.err(598):  at org.jivesoftware.smack.XMPPConnection.initConnection(XMPPConnection.java:663)
08-12 18:57:36.783: W/System.err(598):  at org.jivesoftware.smack.XMPPConnection.connectUsingConfiguration(XMPPConnection.java:615)
08-12 18:57:36.783: W/System.err(598):  at org.jivesoftware.smack.XMPPConnection.connect(XMPPConnection.java:1034)

자세한 원인은 모르겠지만 여러번 테스트와 약간의 소스를 확인한 결과 
잘못된 connect 루틴을 사용한 사소한 문제로 발생된 것으로 판단.

Smack에서 제공하는 connect의 sample 예제는 다음과 같다.
일반적으로 connection configuration을 만들고 이를 사용하여 connect를 하고 login을 하게 됨.

 // Create the configuration for this new connection
ConnectionConfiguration config = new ConnectionConfiguration("jabber.org", 5222); config.setCompressionEnabled(true); config.setSASLAuthenticationEnabled(true); Connection connection = new XMPPConnection(config); // Connect to the server connection.connect(); // Log into the server connection.login("username", "password", "SomeResource"); .... // Disconnect from the server connection.disconnect();

하지만 이를 reconnect 상황에서 그래도 사용할 경우 위와 같은 현상이 발생하는 것으로 보이고
로그상에서의 표면적인 원인은 MultiUserChat에서 사용하는 ServiceDiscoveryManager의 instance가 null이라 발생함.
더 세부적인 원인으로는 새롭게 생성하려는 XMPPConnection이 network 상황들로 인해 제대로 configuration이 되지 않은 상태에서 connection을 시도하여 발생한 것으로 그냥 추측만 할 뿐.. 자세한 내용을 알려면 XMPP spec 과 smack initialize 코드를 봐야 함. ㅜㅜ 나중에...

그래서 임시적인 solution으로는 
reconnect 상황에서 connection이 null 이 아닌 경우에만 connection을 생성하여 NullPointerException을 방지하고
불필요한 login도 줄여서 reconnect 함. 대충 아래와 같이?

 if(null == conn_){
connection = new XMPPConnection(config);
}
connection.connect();
if(false == conn_.isAuthenticated()){
connection.login(_info_.getXmppId(), password);
}


** 추가로 재접속 시에 connection이 끊겼다고 해서 굳이 disconnect를 할 필요가 없다.
smack에서는 자동적으로 connection을 timout을 조정하면서 재 연결하려는 시도를 하고 있고 이를 좀 더 즉각적으로 하기 위해서는 connect를 명시적으로 호출할 경우 재접속 시도는 cancel되고 바로 connect를 시도하게 된다. 
이 때 disconnect를 호출하게되면 재접속 시도를 명시적으로 cancel하게 하는 것이라 완전히 종료를 위해서만 사용하는게 맞겠음.

 Connections can be reused between connections. This means that an Connection may be connected, disconnected and then connected again. Listeners of the Connection will be retained accross connections.

If a connected Connection gets disconnected abruptly then it will try to reconnect again. To stop the reconnection process, use disconnect(). Once stopped you can use connect() to manually connect to the server.

 By default Smack will try to reconnect the connection in case it was abruptly disconnected. Use ConnectionConfiguration#setReconnectionAllowed(boolean) to turn on/off this feature. The reconnection manager will try to immediately reconnect to the server and increase the delay between attempts as successive reconnections keep failing. 
In case you want to force a reconnection while the reconnetion manager is waiting for the next reconnection, you can just use Connection#connect() and a new attempt will be made. If the manual attempt also failed then the reconnection manager will still continue the reconnection job.



[Multi User Chat extension을 사용하여 채팅 시 메시지 중복 수신 현상]

# precondition
  : XMPP connection이 close 된 후 재 연결된 상태
  : MUC(Multi User Chat) extension을 사용하여 채팅 중

- 사용자가 전송한 메세지가 중복으로 수신되는 현상

좀 바보같은 이유때문에 발생한 현상이지만 그래도 XMPP spec과 smack library의 특성으로 인해 충분히 발생할 상황이라 정리

multiuser chat에서의 join 예제를 보면 다음과 같고 
// Create a MultiUserChat using a Connection for a room
<pre style="font-family: 'courier new', monospaced;">      MultiUserChat muc2 = new MultiUserChat(conn1, "myroom@conference.jabber.org");

      // User2 joins the new room using a password
      // The room service will decide the amount of history to send
      muc2.join("testbot2", "password");</pre>
smack API reference에서는 join류 API들을 다음과 같이 설명하고 있음.
bold체로 되어있는 부분에서는 join을 호출하면 기존 muc room을 leave하고 join한다고 되어 있음.

 join
public void join(java.lang.String nickname) throws XMPPException

Joins the chat room using the specified nickname. If already joined using another nickname,this method will first leave the room and then re-join using the new nickname.The default timeout of Smack for a reply from the group chat server that the join succeeded will be used. After joining the room, the room will decide the amount of history to send.



<dl style="color: rgb(0, 0, 0); font-family: Gulim; font-size: medium; line-height: normal;">
Parameters:
nickname - the nickname to use.
Throws:
XMPPException - if an error occurs joining the room. In particular, a 401 error can occur if no password was provided and one is required; or a 403 error can occur if the user is banned; or a 404 error can occur if the room does not exist or is locked; or a 407 error can occur if user is not on the member list; or a 409 error can occur if someone is already in the group chat with the same nickname.
</dl>


하지만 asmack을 사용해서 테스트 해보니 좀 이상하다.
leave가 제대로 안되는 것인지는 모르겠지만 
connection이 재설정되는 상황에서 
 - re-join을 하지 않을 경우 메세지 송수신이 되지 않고
 - leave를 명시적으로 호출하지 않고 re-join을 하게 될 경우 메세지가 중복되어 수신된다.
 - leave를 명시적으로 호출하고 re-join을 하게 될 경우 메세지가 정상적으로 하나만 수신된다.

암튼 내가 잘못 코딩한것일 수 도 있을 수도 있으니 좀 더 테스트는 필요하겠음.



2013년 8월 6일 화요일

StarUML 시작 시 에러 메세지(Cannot focus a disabled or invisible window)

이전 블로그에서 이전 함 (원본 글 2013/08/06 작성)

한동안 계속 "Cannot focus a disabled or invisible window" 에러 메시지가 
StarUML 시작 시 발생되어 귀찮았었음.

하지만 감사합니다. 궁댕이 스토리 님 :)


 최근 직장을 옮기고 좀더 많은것을 배우고 많은것을 체험해 보려고 UML프로그램 을 설치했다.
같이 일하시는 분께서 추천해주신 StarUML 을 설치해서 사용했었다.
잘 사용하고 있는데 어느날부턴가 실행하면 "
Cannot focus a disabled or invisible window" 메세지가 뜨고
사용하는 도중 오류 발생하면서 죽는거다.
그래서 좀 짜증났는데 그냥 두었다.
그런데 오늘 다시 쓰려고 켜보니 또 매한가지인거다.

구글링 통해서 알아보니 약간 버그인듯하더라.
"Model Explor" 을 자동숨김(핀셋고정안한상태)으로 해놓으면 이런문제가 발생한다고 한다.
다시 고정상태로 두니 신기하게도 오류는 사라졌다.

StarUML에서 ER diagram 그리기

이전 블로그에서 이전 함 (원본 글 2013/08/06 작성)

StarUML


오픈소스 UML modeling s/w 중에서는 가장 완성도 있음.
다만 추가 개발 및 버그 수정은 중단된 상태이고 eclipse 기반 java 버전을 2010년 부터 개발한다고 하지만 무소식.

기본적인 UML diagram들을 그리는데는 부족함이 없고
추가 module(기능)들을 Plugin으로 추가하여 사용 가능함.



StarUML에서는 Plugin으로
DB의 관계를 도식화 할 수 있는 Entity-Relation Diagram을 그릴 수 있는
ER Diagram Notation Extension을 제공함.


[설치 방법]
 How to install a module?
Installing a module is very simple.
  1. Download a module distribution package (.zip)
  2. Extract the file on StarUML module directory (e.g. C:\Program Files\StarUML\modules)

이해가 안된다면 아래 동영상 참고

 => 동영상을 통한 다운로드, 설치, 실제 ER diagram 그리기를 보여주고 있음.
 . 다운로드 => 45초
 . 압축해제 및 설치 => 54초
 . ER diagram 추가 => 2분 06초
 . Table 추가 => 2분 20초
 . PK, FK 설정 => 2분 45초
 . stereo type을 table로 설정 => 3분 43초
  : 중요한 것은 ER diagram 그릴 때 table의 Stereo type을 'table'로 설정하는 것.
    기본적으로 ERD의 table이 아닌 UML standard의 table로 설정이 되어 있어 변경 필수!!!
 . Table Relation 설정 => 4분 10초 

[기타 링크]
: 간단 설치 가이드

Android SQLite Cursor 관리, close 시점

이전 블로그에서 이전 함 (원본 글 2013/08/06 작성)

Android SQLite를 사용하다 Cursor의 close 시점이 궁금해서 찾아봄.

일단 Query 이후 전달되는 Cursor는 데이터를 다른 data structure에 저장을 하고 바로 close하는 게 바람직해 보이나
과도한 query로 인한 activity 사용성 문제와 activity의 state 변경으로 인한 cursor 처리를 위해 Loader를 구현해서 적절히 처리하는게 맞겠음.
만약 data를 소비하는 측이 다른 process에 존재한다면 ContentProvider를 구현해서 처리하는 게 맞음.

[startManagingCursor(), CursorLoader]

Cursor를 자동으로 관리해 주는 startManagingCursor() 는 deprecate 되었고
CursorLoader와 LoaderManager를 사용하라고 권고 하고 있음.


 public void startManagingCursor (Cursor c)
Added in API level 1

This method was deprecated in API level 11.
Use the new CursorLoader class with LoaderManager instead; this is also available on older platforms through the Android compatibility package.
This method allows the activity to take care of managing the given Cursor's lifecycle for you based on the activity's lifecycle. That is, when the activity is stopped it will automatically call deactivate() on the given Cursor, and when it is later restarted it will call requery() for you. When the activity is destroyed, all managed Cursors will be closed automatically. If you are targeting HONEYCOMB or later, consider instead using LoaderManager instead, available via getLoaderManager().
Warning: Do not call close() on cursor obtained from managedQuery(Uri, String[], String, String[], String), because the activity will do that for you at the appropriate time. However, if you call stopManagingCursor(Cursor) on a cursor from a managed query, the system will not automatically close the cursor and, in that case, you must call close().

= CursorLoader
public class

CursorLoader
 

extends AsyncTaskLoader<D> 
   ↳

   ↳


   ↳
android.content.CursorLoader

Class Overview


A loader that queries the ContentResolver and returns a Cursor. This class implements the Loader protocol in a standard way for querying cursors, building on AsyncTaskLoader to perform the cursor query on a background thread so that it does not block the application's UI. 


= LoaderManager
 : 링크에 simple cursor example 포함.
 public abstract class
LoaderManager
extends
 Object 
   ↳
android.app.LoaderManager

Class Overview


Interface associated with an Activity or Fragment for managing one or more Loader instances associated with it. This helps an application manage longer-running operations in conjunction with the Activity or Fragment lifecycle; the most common use of this is with a CursorLoader, however applications are free to write their own loaders for loading other types of data. While the LoaderManager API was introduced in HONEYCOMB, a version of the API at is also available for use on older platforms throughFragmentActivity. See the blog post Fragments For All for more details.


startManagingCursor()의 단점과 Loader, LoaderManager에 대한 설명은 다음 블로그에서 잘 정리하고 있음.


간단 요약
 - managedQuery() (startManagingCursor())은 사용자가 신경 쓸 필요 없이 activity에서 관리를 하게 하지만
    main UI thread 상에서 query를 실행하여 처리하다 보니 반응성 측면에서 문제가 될 수 있고
    activity의 상태 변경으로 인한 변화에 따라 cursor()를 적절히 처리하지 못함.
 - Loader를 통해서 application은 data loading을 별도의 thread에서 asynchronous 하게 처리할 수 있고 loading result 및 update 관련된 사항을 callback을 통해서 처리할 수 있음. 또한 Loader는 명시적인 states(started, stopped, reset 등)에 대해서 대응 할 수 있음.
* 자세한 내용은 읽어 보는 것을 추천...


[Cursor 관련 QnA]
: DB close는 provider가 처리, cursor은 사용이 끝난 시점에 close

: 항상은 아니지만 코딩상 실수로 이런 경우도 있을 것 같음. :)
 "close() was never explicitly called on database xxx" 라는 메세지가 나오는 경우 한번에? db를 여러번 열지 않았는지 확인 필요
 I resolved the exception. I was calling
db = eventsData.getReadableDatabase();
twice thats why the exception is thrown


[ContentProvider 구현]

나중에 자세히 봐야 할듯...

 : ContentProvider 설명
 : ContentProvider 만들기 


 : ContentProvider 관련 개념 설명 및 practice