2. About me
● GDG Korea Android 운영자
○ GDG Korea Android
○ http://goo.gl/62bGk
● Google Developers Expert
● Thinkware
3. 발표 자료에 대해
이 발표자료는 저, 양찬석님, 전병권님이 작성한 자료를 기
준으로 하고 있습니다.
발표자료의 내용은 자유롭게 인용, 발췌할 수 있습니다.
4. Activity Stack?
● 웹 브라우져에는 왜 저렇게 탭이 많지?
● 앱들이 상호작용한다면 모바일 운영체제도
웹 브라우저 처럼 많은 앱이 열리게 될 것임.
● 관리할 방법이 필요함.
5. Activity Stack
● 연속된 작업 흐름끼리 쌓아 올리자.
● 카드덱 1) 메일을 읽던 중 링크를 클릭해서 웹
페이지를 본다.
● 카드덱 2) 사진 촬영 후에 포토원더에서 사진
을 편집한다.
● 다른 카드 덱으로 전환: 태스크 전환 버튼
● 카드 덱의 카드 제거: 백 버튼
6. 닌겐노 건망증와 튼튼데스네.
지금 메일을 작성중입니다. 그전에는 무얼 했을
까요?
1. 친구 목록을 보다가 이메일 링크를 클릭했습
니다.
2. 노티피케이션을 보고 이메일을 클릭해서 답
장을 합니다.
3. 메일을 읽다가 답장을 합니다.
4. 메일 앱을 클릭해 들어와 메일을 작성합니다.
사용자는 3분만 지나도 뭘 했는지 모릅니다.
백 버튼으로 이전 상태로 가는 것이 적절할까
9. 액션바
1. 업 버튼
a. 캐럿 (<) - 업 네비게이션 가능.
b. 로고나 아이콘이 같이 표현
2. 현재 위치나 이동할 수 있는 곳을 표현.
a. 탭이나 드로어 메뉴도 사용 가능.
3. 무엇을 할 수 있는지를 표현.
a. 액션 버튼. 넘친 항목은 오른 쪽 끝에 점 세개(4)로 표
10. 액션바는 허니컴 이후에만 되는 것 아네
요?
http://actionbarsherlock.com/
프로요까지 지원. 구글도 씁니다.
Jake Wharton (스퀘어)
19. 서랍 메뉴 (Drawer Menu)
● 페이스북으로 부터 유행
했던 UI 안드로이드에서
공식 지원
● 어떠한 경우에도 액션바
가 움직이지 않는 것이
안드로이드 스타일.
20. ● 캐럿 대신에 햄버거 (석삼)이 표시됨
● 메뉴가 열릴 때 상단의 항목은 그대로 배열되
고 햄버거의 가로폭만 좁아진다.
● http://goo.gl/LF0nv
21.
22.
23. 더블 버퍼링, 트리플 버퍼링, VSync
● 젤리빈에서 트리플 버퍼링과 VSync 도입?
● 화면에 보여지는 영역: 프레임 버퍼
● 더블 버퍼링: 프레임 버퍼외 백 버퍼를 하나
두는 것.
○ 백버퍼 없이 프레임 버퍼에 그리면 그리는 과정 전체
가 보이게 됨.
○ 백버퍼에 내용을 그린 다음 프레임 버퍼에 고속 복사
하는 방식으로 구현.
○ 문제 주사되는 시점에 복사가 이루어지면 화면의 일
부만 복사된 상황에서 표시됨. (티어링 현상)
24. 더블 버퍼링, 트리플 버퍼링, VSync
● 더블 버퍼링 + VSync
○ VSync는 주사 주기를 하드웨어로 부터 받아와서 참
고하는 것으로 티어링을 피할 수 있다.
○ 이번 주사 주기에 다 못 끝내면 다음 주사 주기까지
기다려야 한다.
○ 렌더링 실패시 성능은 1/N으로 떨어진다.
60 프레임 -> 30프레임 -> 20프레임 -> 10프레임.
● 트리플 버퍼링 + VSync
○ 백 버퍼를 하나 더 두어서 주사 주기를 기다리는 동안
다른 프레임을 그리자.
○ 밀린 프레임은 해당 프레임에서 밀림.
○ 백버퍼의 용량이 추가로 필요.
42. 에니메이션을 빠르게 하는 방법은 없나
요? (JB)
객체의 프로퍼티
에 대한 디스플레
이 리스트가 확
장.
(DLProps)
● alpha
● translationX/Y
● scaleX/Y
● rotationX/YViewPropertyAnimator(HC 12), ObjectAnimator (HC 11)
53. 비동기 처리
● 일정 시간 이상 메인스레드가 동작하지 않으
면 ANR 에러.
○ 안드로이드는 UI가 메인스레드에서 동작해야 한다.
(아이폰도 UI는 메인스레드에서 존재. 에니메이션만
별도 스레드)
○ DB, 쉐어드프리퍼런스, 파일, 네트워크는 백그라운드
처리되어야 함
54. 비동기 처리
● AsyncTask 모델
○ 백그라운드에서 처리해서 메인스레드에 갱신함.
○ 작업용 메서드, 후작업용 메서드를 오버라이드하는
형태.
○ 일시적으로 사용할때만 적합하다. (반복적으로
AsyncTask를 호출해야할 수 있음)
○ 엑티비티가 화면 전환 등으로 상태를 잃어버려 계속
호출할 수 있음.
● 스레드 모델
○ 메인 스레드와 연결된 핸들러를 이용해야 함.
○ 장기적으로 사용할 수는 있음.
○ 스레드를 만들어서 관리해야하는 것이 불편.
55. 비동기 처리
● 로더
○ 생명주기에 맞추어 작동하는 도구.
○ 액티비티 상황에 따라 움직이는 것은 편리.
○ 장기적인 작업에는 적당하지 않음.
● 서비스
○ 장기적인 작업에 대한 유일한 답.
○ 별도의 스레드를 만들어야 하는 것은 불편.
56. 배터리
● 라디오 대기, 라디오 저전력, 라디오 풀 파워
의 상태.
● 라디오 대기는 최소 전력이지만 네트워크 지
원하지 않음.
● 상태 전환 마다 레이턴시가 있고 효율을 위해
낮은 상태로 가는 것이 더 길게 설정되어 있
음.
57. 배터리
● 최악의 경우:
○ 네트워크 통신을 1초동안 한다.
○ 18초 마다 통신을 한다.
○ 1초동안 네트워크 연결을 위해 2초 소모.
○ 17초간 절전 모드 들어가지 않음.
● 나누어서 네트워크 잡지 마세요.
63. ● (HTTP와는 달리) 바이너리 기반 효율적.
● 여러 요청을 한번에 처리.
● HTTP 의 헤더도 압축. (HTTP는 본문만 압축)
● 다른 스트림의 끼어듬 허용. 우선 순위.
● 서버 푸쉬 가능 (이 부분만 웹 앱을 새로 적용
해야)
○ 필요한 이미지나 CSS, JS를 같이 푸쉬시킬 수 있음.
64. OkHTTP
● HTTPUrlConnection과 동일한 인터페이스
● GZIP 압축 지원.
● 캐쉬 지원.
● SPDY 지원.
● 커넥션 풀링 지원.
http://square.github.io/okhttp/ Jesse Wilson
(스퀘어, 전직 안드로이드 HTTP 파트 리드)
65. Retrofit
HTTP REST 처리 라이브러리. (http://square.github.io/retrofit/)
public interface GitHubService {
@GET("/users/{user}/repos")
List<Repo> listRepos(@Path("user") String user);
}
GitHubService service = restAdapter.create(GitHubService.
class);
List<Repo> repos = service.listRepos("octocat");
66. HTTP / 이미지 라이브러리 샘플들
http - OkHTTP 간단한 샘플로 main함수가 있는 코드들이 있습니다.
https://github.com/swankjesse/android-http-examples/tree/master/http
picasso-app - 스퀘어의 이미지 라이브러리 피카소에 대한 샘플들입니다.
https://github.com/swankjesse/android-http-examples/tree/master/picasso-app
retrofit-app - 역시 스퀘어가 만든 어노테이션 기반의 HTTP(JSON) 도구 레트로
핏에 대한 샘플들입니다.
https://github.com/swankjesse/android-http-examples/tree/master/retrofit-app
volley-app - 구글이 만든 발리 라이브러리에 대한 샘플입니다.
https://github.com/swankjesse/android-http-examples/tree/master/volley-app
69. @EActivity(R.layout.translate) // Sets content view to R.layout.translate
public class TranslateActivity extends Activity {
@ViewById // Injects R.id.textInput
EditText textInput;
@ViewById(R.id.myTextView) // Injects R.id.myTextView
TextView result;
@AnimationRes // Injects android.R.anim.fade_in
Animation fadeIn;
@Click // When R.id.doTranslate button is clicked
void doTranslate() {
translateInBackground(textInput.getText().toString());
}
@Background // Executed in a background thread
void translateInBackground(String textToTranslate) {
String translatedText = callGoogleTranslate(textToTranslate);
showResult(translatedText);
}
@UiThread // Executed in the ui thread
void showResult(String translatedText) {
result.setText(translatedText);
result.startAnimation(fadeIn);
}
// [...]
}
70. Otto
http://square.github.com/otto/
Otto is an event bus designed to decouple different parts of your application
while still allowing them to communicate efficiently.
Forked from Guava, Otto adds unique functionality to an already refined
event bus as well as specializing it to the Android platform.
Guava
The Guava project contains several of Google's core libraries
that we rely on in our Java-based projects: collections,
caching, primitives support, concurrency libraries, common
annotations, string processing, I/O, and so forth.
74. 여러 프래그먼트를 사용하는 앱
A B C 1. 인터페이스를 만듭니다.
2. 인터페이스를 구현합니다.
3. 프래그먼트로 메시지를 전달합니다.
다른 프래그먼트와 소통하기
http://developer.android.com/training/basics/fragments/communicating.html
75. public static class MainActivity extends Activity
implements FragmentA .OnFragmentListener, FragmentB.OnFragmentListener, FragmentC.OnFragmentListener {
....
@Override
public void onFragmentA () {
}
public void onFragmentB() {
}
}
public class FragmentA extends Fragment {
OnFragmentListener mCallback ;
// Container Activity must implement this interface
public interface OnFragmentListener {
public void onArticleSelected (int position );
}
@Override
public void onAttach (Activity activity ) {
super.onAttach (activity );
try {
mCallback = (OnFragmentListener ) activity ;
} catch (ClassCastException e) {
throw new ClassCastException (activity .toString ()
+ " must implement OnFragmentListener" );
}
}
...
}
1. 인터페이스 정의하기
2. 인터페이스 구현하기
76. public static class MainActivity extends Activity
implements FragmentA .OnFragmentListener, FragmentB.OnFragmentListener, FragmentC.OnFragmentListener {
...
public void onArticleSelected (int position ) {
// The user selected the headline of an article from the FragmentA
// Do something here to display that article
FragmentA articleFrag = (FragmentA )
getSupportFragmentManager ().findFragmentById (R.id.article_fragment );
if (articleFrag != null) {
// If article frag is available, we're in two-pane layout...
// Call a method in the ArticleFragment to update its content
articleFrag .updateArticleView (position );
} else {
// Otherwise, we're in the one-pane layout and must swap frags...
// Create fragment and give it an argument for the selected article
FragmentA newFragment = new FragmentA ();
Bundle args = new Bundle();
args .putInt(FragmentA .ARG_POSITION , position );
newFragment .setArguments (args);
FragmentTransaction transaction = getSupportFragmentManager ().beginTransaction ();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction .replace(R.id.fragment_container , newFragment );
transaction .addToBackStack (null);
// Commit the transaction
transaction .commit();
}
}
}
3. 프래그먼트로 메시지 전달하기
77. 3단계 Otto
1. 이벤트 버스를 만듭니다.
2. 이벤트를 발행합니다.
3. 이벤트를 구독합니다.
@Subscribe
public void answerAvailable (AnswerAvailableEvent event) {
// TODO: React to the event somehow!
}
bus.register(this);
bus.post(new AnswerAvailableEvent (42));
Bus bus1 = new Bus();
Bus bus2 = new Bus(ThreadEnforcer .MAIN);