0
안드로이드,오픈 소스, 그리고 패턴
손영수   EngFlip팀
요즘 업계 흐름은알고 가시죠 ^^
Google이  꿈꾸는..Android의 미래
Google은왜 MODU의  특허를50억에 샀을   까?
MODU의 Jacket 시스템
이게왜 중요하지?..
사실 Google의서비스는 Cloud에..
Android는 Google의 서비스를(개인, 가정이) 소비하게 만드는 Hub
Android는   더 이상Gadget을 위한 OS가 아니다.
Embedded  System을포괄할 OS로 봐야 함.
하지만..
제조사 입장에서Android@Home은 독이 든 성배.
Welcome to myJourney!
Agenda• 안드로이드 이해 – Binder (Broker 패턴) 그리고 Intent• 오픈 소스 그리고 사례 – Simple Framework (Parameter Object) – 불편하지 않은 화면 갱신 (Publ...
# 1. Binder..
ContentsActivity           Provider           BroadcastService           Reciever
하지만…   우리가주목해야 할 것은..
왜 Binder가중요하지?
Android 내의  모든 상황을감독하는 감시관!
갑자기 뚝 하고나온 녀석이 아니다.    아주..일반적인 아키텍쳐일뿐.
Binder Architecture                        IDL                        Compiler                              in args       ...
Binder를느낄 수 있는 예제  AIDL 샘플 참고http://bit.ly/85E5SV
1. AIDL 파일 생성package aexp.aidl;  // Adder service interface.  interface IAdderService {      int add( in int i1, in int i2...
2. AIDL 툴로 Java 파일 생성수동 코드 생성sdk/platforms/android- <n>/tools/aidl 에 간다C:Android-projectApiDemossrccomexampleandroidapisap...
3. Service Class 구현……public class AdderServiceImpl extends Service {    @Override    public IBinder getBinder() {       re...
4. Manifest에 서비스 등록<manifest xmlns:android="http://schemas.android.com/apk/res/android"  package="aexp.aidl">  <applicatio...
5. Client에 호출을 위해               Binder로 이름 찾는 로직class AdderServiceConnection implements ServiceConnection  {    public voi...
6. 시작, 해제 로직 넣을 것private void initService(){     conn = new AdderServiceConnection();     Intent i = new Intent();     i.s...
7. 클라이언트에서 서비스 호출하기private void invokeService( int i1, int i2 ) {      TextView t = (TextView)findViewById(R.id.invokeserv...
Broker                      transfer                        transfer                      message                         ...
Registration        Service, BR, Activity…                     Brokerstart               Initialize()                     ...
Sending Request          Client              Client-Side      Broker                  Server-Side          Server         ...
사용하기           힘든 Binder..    Intent는 Binder를쉽게 사용할 수 있는 추상화 도구.
Intent를 잘 알면. Android를 잘~~ 개발 할 수 있다.
Intent로 Activity 호출Intent intent =new Intent(getApplicationContext(), MyOtherActivity.class);startActivityForResult(intent...
그래서 묵시적 IntentManifest 파일에 Intent Filter 등록<activity android:name="DirectoryDialog"    android:theme="@android:style/Theme...
# 2.아직도 Logcat?
여러분이 만든 시스템이    죽었다.  미국에서….
Logcat 보러 출장?
새로운 log..    4
먼저Log Management   패턴부터…
log4xxx
Microlog4android 사용법• http://code.google.com/p/microlog4android/downloads/에서  microlog4android-1.0.0.jar 다운• Android 프로젝트에...
public class LogtestActivity extends Activity {static public Logger logger = LoggerFactory.getLogger();  @Override  public...
로그를Network 서버로 보내는   Appender도 있으나 약간의 코딩이 필요.
# 3. REST의 귀찮음.    Rest is unrest..
StubController          DAO  Proxy      REST    DTO             GET
같이 뭉쳐 다니는 파라메터는ParameterObject로 묶어라!
XML 파싱 이렇게??                                  while(true) {<categoryList>                        int eventType = xpp.nextT...
Simple Framework를     이용하세요.http://simple.sourceforge.net/
이렇게 됩니다.<categoryList>                      @Root  <categorys>                       public class CategoryList {     <cate...
이렇게 됩니다.        while(true) {            int eventType = xpp.nextTag();            if(eventType == XmlPullParser.START_TAG...
# 4. 화면 갱신
My Market을 기억하시나요?
시작하자마자Loading.. 화면이 뜨면 누가 접속하나요??
시작하자 마자 화면이 나오게.
그럼. 사용자가직접 당겨서 동기화를?
Sync        Notificati                          Service        on                                    2. InsertActivity    ...
@Overridepublic Uri insert(Uri uri, ContentValues values) {            String tableName;            Uri contentUri;       ...
# 5. 분석은 어떻게?
영어발음 트레이너
영어발음 트레이너사용자의 패턴분석
모바일 어플리케이션  분석 플랫폼
메인 DASHBOARD
Daypart
Device
App Version
TagEvent
이외에도..•   New vs Returning•   Carrier•   Country•   OS Version
적용방법• http://www.localytics.com/에서•             탭 에서 어플리케이션 등록
• http://bit.ly/KnZzpx 에서 소스코드 다운• Android 프로젝트 src/폴더에 소스코드 추가• AndroidManifest.xml에 퍼미션 추가<uses-permission android:name=...
• Main Activity에 Import       import com.localytics.android.*;• 클래스 내부에 session object 추가       private LocalyticsSession ...
• onResume 메소드 Override  public void onResume()  {     super.onResume();     this.localyticsSession.open();  }• onPause 메소...
• TagEvent남기기 localyticsSession.tagEvent(“TagEvent남김 ");
# 6. 1000 피트의 뷰.
높이 (30000 feet)봐야 할까?
높이 봐야 할까?
자세히 (0 feet) 봐야 할까?
자세히 봐야 할까?
3만 피트 vs 0 피트의 뷰.      3만 피트      • 다이어그램의 Line의 의미는?       • 의존성?       • 데이터 흐름?       • 버스와 같은 공유자원?          0 피트     ...
해결책은..적절한 1000 피트의 뷰
STAN (Structure Analysis for Java)STAN - http://stan4j.com/eclipse/eclipse-integration.html
Robert C. Martin의 그래프
Instability•패키지의 움직일             수 있는 여력을 판단하는지표•다른 패키지에 영향을 미치지 않고, 해당 패키지를 쉽게 변경 할 수 있는가?•Instability I = Ce / (Ca+Ce)•C...
Instability                  Instability I = Ce / (Ca+Ce)당신의 패키지가 다른 사람이 많이 쓴다면,즉 Outgoing, Ce가 많다면, 여러분의 패키지는 변경하기 어렵다.반대...
Abstractness  Interface(Abstract) 와 Concrete Class를 비교A = (#abstract classes / total # of classes)  •Abstract class = inte...
다시 보는 그래프        다른데서 많이 쓰는         녀석이니 조금 더        abstract를 높여야               돼!
그 외 용어•Tangled Complexity •순환 참조가 있어 Boundary를 깰 때•Cyclomatic Complexity •분기 문이 많아 hotspot이 될 가망성이 높은 곳
경고!!!환자의 외부 증상만고치는 의사가 되지 말자!!이러한 정보는 좋은 가이드일뿐!!숫자에 의존하다가오히려 아키텍쳐가 무너진다.
# 7. UI Patterns      다양한 안드로이드 UI 기법을 소개       http://bit.ly/QyDjMV
Android UI Pattern App                           다양한                       안드로이드 UI 기법을                        오픈 소스로 공개ht...
Android UI Pattern App
Android UI Pattern App
예제 1 - android-actionbar
스크린샷1   스크린샷2   XML   기능   Action   Action예제   색변경
스크린샷1   스크린샷2   XML   기능   Action   Action예제   색변경
스크린샷1   스크린샷2   XML   기능   Action   Action예제   색변경
스크린샷1   스크린샷2   XML   기능   Action   Action예제   색변경
스크린샷1   스크린샷2   XML   기능   Action   Action예제   색변경
스크린샷1   스크린샷2   XML   기능   Action   Action예제   색변경
colors.xml 스크린샷1   스크린샷2   XML   기능   Action   Action예제   색변경
예제 2android-binding-frameworkhttp://code.google.com/p/android-binding/http://bit.ly/cxxwCF
Event에 대한 Binding다음과 같이 버튼에 대한 이벤트Method OnClick()
Main.xml
CalculateViewModel.java
Option.xml
Main Activity
Main Activity
Q &A
안드로이드 오픈소스 그리고 패턴
안드로이드 오픈소스 그리고 패턴
안드로이드 오픈소스 그리고 패턴
안드로이드 오픈소스 그리고 패턴
안드로이드 오픈소스 그리고 패턴
Upcoming SlideShare
Loading in...5
×

안드로이드 오픈소스 그리고 패턴

10,009

Published on

안드로이드 개발시 필요한 오픈소스, 패턴, 개념들을 설명

Published in: Technology
0 Comments
22 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
10,009
On Slideshare
0
From Embeds
0
Number of Embeds
7
Actions
Shares
0
Downloads
154
Comments
0
Likes
22
Embeds 0
No embeds

No notes for slide
  • http://myossdevblog.blogspot.com/2009/03/microlog4android.html
  • Transcript of "안드로이드 오픈소스 그리고 패턴 "

    1. 1. 안드로이드,오픈 소스, 그리고 패턴
    2. 2. 손영수 EngFlip팀
    3. 3. 요즘 업계 흐름은알고 가시죠 ^^
    4. 4. Google이 꿈꾸는..Android의 미래
    5. 5. Google은왜 MODU의 특허를50억에 샀을 까?
    6. 6. MODU의 Jacket 시스템
    7. 7. 이게왜 중요하지?..
    8. 8. 사실 Google의서비스는 Cloud에..
    9. 9. Android는 Google의 서비스를(개인, 가정이) 소비하게 만드는 Hub
    10. 10. Android는 더 이상Gadget을 위한 OS가 아니다.
    11. 11. Embedded System을포괄할 OS로 봐야 함.
    12. 12. 하지만..
    13. 13. 제조사 입장에서Android@Home은 독이 든 성배.
    14. 14. Welcome to myJourney!
    15. 15. Agenda• 안드로이드 이해 – Binder (Broker 패턴) 그리고 Intent• 오픈 소스 그리고 사례 – Simple Framework (Parameter Object) – 불편하지 않은 화면 갱신 (Publisher-Subscriber)• 분석 방법 – Localytics 사용법 – STAN을 이용한 Android App 분석 방법
    16. 16. # 1. Binder..
    17. 17. ContentsActivity Provider BroadcastService Reciever
    18. 18. 하지만… 우리가주목해야 할 것은..
    19. 19. 왜 Binder가중요하지?
    20. 20. Android 내의 모든 상황을감독하는 감시관!
    21. 21. 갑자기 뚝 하고나온 녀석이 아니다. 아주..일반적인 아키텍쳐일뿐.
    22. 22. Binder Architecture IDL Compiler in args operation() Client Object OBJ REF out args, return IDL SKEL IDL Binder STUBS INTERFACE Object AdapterBinder
    23. 23. Binder를느낄 수 있는 예제 AIDL 샘플 참고http://bit.ly/85E5SV
    24. 24. 1. AIDL 파일 생성package aexp.aidl; // Adder service interface. interface IAdderService { int add( in int i1, in int i2 ); }
    25. 25. 2. AIDL 툴로 Java 파일 생성수동 코드 생성sdk/platforms/android- <n>/tools/aidl 에 간다C:Android-projectApiDemossrccomexampleandroidapisapp>aidl -IC:Android- projectApiDemossrc IRemoteService.aidlEclipse에서는 aidl만 넣고 빌드하면 자동으로 소스 생성 됨
    26. 26. 3. Service Class 구현……public class AdderServiceImpl extends Service { @Override public IBinder getBinder() { return mBinder; } @Override public void onCreate() { super.onCreate(); Log.d( "ADDERSERVICEIMPL","onCreate" ); } /** The IAdderService is defined through IDL */ private final IAdderService.Stub mBinder = new IAdderService.Stub() { public int add( int i1, int i2 ) { return i1+i2; } }; @Override protected void onDestroy() { super.onDestroy( Log.d( "ADDERSERVICEIMPL","onDestroy" ); }}
    27. 27. 4. Manifest에 서비스 등록<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="aexp.aidl"> <application> <activity class=".AIDLServiceActivity" android:label="AIDLServiceActivity"> <intent-filter> <action android:value="android.intent.action.MAIN" /> <category android:value="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service class=".AdderServiceImpl"/> </application></manifest>
    28. 28. 5. Client에 호출을 위해 Binder로 이름 찾는 로직class AdderServiceConnection implements ServiceConnection { public void onServiceConnected(ComponentName className, IBinder boundService ) { service = IAdderService.Stub.asInterface((IBinder)boundService); Log.d( "ADDERSERVICECLIENT","onServiceConnected" ); } public void onServiceDisconnected(ComponentName className) { service = null; Log.d( "ADDERSERVICECLIENT","onServiceDisconnected" ); } };
    29. 29. 6. 시작, 해제 로직 넣을 것private void initService(){ conn = new AdderServiceConnection(); Intent i = new Intent(); i.setClassName( "aexp.aidl", "aexp.aidl.AdderServiceImpl" ); bindService( i, null, conn, Context.BIND_AUTO_CREATE);}private void releaseService(){ unbindService( conn ); conn = null;}
    30. 30. 7. 클라이언트에서 서비스 호출하기private void invokeService( int i1, int i2 ) { TextView t = (TextView)findViewById(R.id.invokeserv_result); if( service == null ) t.setText( "Service not available" ); else { try { int result = service.add( i1,i2 ); t.setText( Integer.toString( result ) ); } catch( DeadObjectException ex ) { t.setText( "Service invocation error" ); } } ….
    31. 31. Broker transfer transfer message message Client-side Broker Server-side Proxy Proxy main_event_loop pack_data pack_data update_repository uppack_data uppack_data register_service send_request call_service acknowledgment return send_response find_server Find_clientcalls Forward_request Forward_response uses API calls uses API calls Client Bridge Server pack_data initialize call_server uppack_data enter_main_loop start_task forward_message run_service use_Broker_API transmit_message use_Broker_API
    32. 32. Registration Service, BR, Activity… Brokerstart Initialize() main_evnet_loop() register_service() update_repository() acknowledgment enter_main_loop()
    33. 33. Sending Request Client Client-Side Broker Server-Side Server Proxy Proxycall_server send_request pack_data forward_request find_server call_service unpack_data run_service forward_response pack_data return find_client unpack_data result
    34. 34. 사용하기 힘든 Binder.. Intent는 Binder를쉽게 사용할 수 있는 추상화 도구.
    35. 35. Intent를 잘 알면. Android를 잘~~ 개발 할 수 있다.
    36. 36. Intent로 Activity 호출Intent intent =new Intent(getApplicationContext(), MyOtherActivity.class);startActivityForResult(intent, SHOW_SUBACTIVITY);그런데, Activity 이름이 바뀌면…
    37. 37. 그래서 묵시적 IntentManifest 파일에 Intent Filter 등록<activity android:name="DirectoryDialog" android:theme="@android:style/Theme.Translucent"> <intent-filter> <action android:name="filemanager.action.PICKFILES" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> Activity 만 되는 </activity>호출Intent filemanager = new Intent("filemanager.action.PICKFILES"); 게 아님startActivity(filemanager);
    38. 38. # 2.아직도 Logcat?
    39. 39. 여러분이 만든 시스템이 죽었다. 미국에서….
    40. 40. Logcat 보러 출장?
    41. 41. 새로운 log.. 4
    42. 42. 먼저Log Management 패턴부터…
    43. 43. log4xxx
    44. 44. Microlog4android 사용법• http://code.google.com/p/microlog4android/downloads/에서 microlog4android-1.0.0.jar 다운• Android 프로젝트에 jar 추가• AndroidManifest.xml에 android.permission.WRITE_EXTERNAL_STORAG​​E 추가
    45. 45. public class LogtestActivity extends Activity {static public Logger logger = LoggerFactory.getLogger(); @Override public void onCreate(Bundle savedInstanceState) { PatternFormatter formatter = new PatternFormatter(); formatter.setPattern( " %d{ISO8601} [%P] %m %T " ); logger.setLevel(Level.INFO); // write to LogCat LogCatAppender logCatAppender = new LogCatAppender(); logCatAppender.setFormatter(formatter); logger.addAppender(logCatAppender); // write to text file of SD-card. FileAppender fileAppender = new FileAppender(); fileAppender.setAppend( true ); fileAppender.setFileName( "microlog4android.log" ); fileAppender.setFormatter(formatter); logger.addAppender(fileAppender);
    46. 46. 로그를Network 서버로 보내는 Appender도 있으나 약간의 코딩이 필요.
    47. 47. # 3. REST의 귀찮음. Rest is unrest..
    48. 48. StubController DAO Proxy REST DTO GET
    49. 49. 같이 뭉쳐 다니는 파라메터는ParameterObject로 묶어라!
    50. 50. XML 파싱 이렇게?? while(true) {<categoryList> int eventType = xpp.nextTag(); <categorys> if(eventType == XmlPullParser.START_TAG) { <category> String tag = xpp.getName(); <id>1</id> if("id".equals(tag)) { <name>AA</name> category.setId(Integer.parseInt(xpp.nextText())); <date>2011-11-01</date> }else if ("name".equals(tag)) { </category> category.setName(xpp.nextText()); <category> }else if ("date".equals(tag)) { <id>2</id> category.setDate(xpp.nextText()); <name>BB</name> }else{ <date>2011-12-10</date> if(XmlPullParser.TEXT == xpp.next()) </category> xpp.nextTag(); </categorys> }</categoryList> } else break; }
    51. 51. Simple Framework를 이용하세요.http://simple.sourceforge.net/
    52. 52. 이렇게 됩니다.<categoryList> @Root <categorys> public class CategoryList { <category> <id>1</id> @ElementList <name>fruit</name> private ArrayList<Category> categorys; <date>201110051200</date> </category> public void setCategorys(ArrayList<Category> categorys) <category> { <id>2</id> this.categorys = categorys; <name>animal</name> } <date>201110051200</date> </category> public ArrayList<Category> getCategorys() { <category> return categorys; <id>3</id> } <name>food</name> } <date>201110051200</date> </category> </categorys></categoryList>
    53. 53. 이렇게 됩니다. while(true) { int eventType = xpp.nextTag(); if(eventType == XmlPullParser.START_TAG) { String tag = xpp.getName(); if("id".equals(tag)) { category.setId(Integer.parseInt(xpp.nextText()));Serializer serializer =}else if ("name".equals(tag)) { new Persister();Reader reader = newcategory.setName(xpp.nextText()); StringReader(xmlData);CategoryList categoryList if ("date".equals(tag)) { }else = serializer.read(CategoryList.class, reader,false); category.setDate(xpp.nextText()); }else{ if(XmlPullParser.TEXT == xpp.next()) xpp.nextTag(); } } else break; }
    54. 54. # 4. 화면 갱신
    55. 55. My Market을 기억하시나요?
    56. 56. 시작하자마자Loading.. 화면이 뜨면 누가 접속하나요??
    57. 57. 시작하자 마자 화면이 나오게.
    58. 58. 그럼. 사용자가직접 당겨서 동기화를?
    59. 59. Sync Notificati Service on 2. InsertActivity 1. Register XXXAdapter 3. Notification Contents Provider 4. GetData..
    60. 60. @Overridepublic Uri insert(Uri uri, ContentValues values) { String tableName; Uri contentUri; long id; switch(matcher.match(uri)){ case SITES: tableName = Bookmark.sites._TABLENAME; ContentValues values = new ContentValues(); contentUri = Bookmark.sites.CONTENT_URI; values.put(Bookmark.sites.NAME, stk[i][0]); break; values.put(Bookmark.sites.ADDRESS, stk[i][1]); default: getContentResolver().insert(Bookmark.sites.CONTENT_URI, values); throw new IllegalArgumentException(); getContentResolver().notifyChange(Bookmark.sites.CONTENT_URI, null); } id = mDB.insert(tableName, null, values); if(id > 0){ Uri itemUri = ContentUris.withAppendedId(contentUri, id); return itemUri; }else throw new SQLException();}
    61. 61. # 5. 분석은 어떻게?
    62. 62. 영어발음 트레이너
    63. 63. 영어발음 트레이너사용자의 패턴분석
    64. 64. 모바일 어플리케이션 분석 플랫폼
    65. 65. 메인 DASHBOARD
    66. 66. Daypart
    67. 67. Device
    68. 68. App Version
    69. 69. TagEvent
    70. 70. 이외에도..• New vs Returning• Carrier• Country• OS Version
    71. 71. 적용방법• http://www.localytics.com/에서• 탭 에서 어플리케이션 등록
    72. 72. • http://bit.ly/KnZzpx 에서 소스코드 다운• Android 프로젝트 src/폴더에 소스코드 추가• AndroidManifest.xml에 퍼미션 추가<uses-permission android:name="android.permission.INTERNET“>
    73. 73. • Main Activity에 Import import com.localytics.android.*;• 클래스 내부에 session object 추가 private LocalyticsSession localyticsSession;• OnCreate 함수에 아래 소스 추가 public void onCreate(Bundle savedInstanceState) { . . . this.localyticsSession = new LocalyticsSession(this.getApplicationContext(), "APP KEY FROM STEP 2"); this.localyticsSession.open(); // open the session this.localyticsSession.upload(); // upload any data . . . }
    74. 74. • onResume 메소드 Override public void onResume() { super.onResume(); this.localyticsSession.open(); }• onPause 메소드 Override public void onPause() { this.localyticsSession.close(); this.localyticsSession.upload(); super.onPause(); }
    75. 75. • TagEvent남기기 localyticsSession.tagEvent(“TagEvent남김 ");
    76. 76. # 6. 1000 피트의 뷰.
    77. 77. 높이 (30000 feet)봐야 할까?
    78. 78. 높이 봐야 할까?
    79. 79. 자세히 (0 feet) 봐야 할까?
    80. 80. 자세히 봐야 할까?
    81. 81. 3만 피트 vs 0 피트의 뷰. 3만 피트 • 다이어그램의 Line의 의미는? • 의존성? • 데이터 흐름? • 버스와 같은 공유자원? 0 피트 • 너무 상세한 정보임. • 전체적인 구조를 보지 못함.
    82. 82. 해결책은..적절한 1000 피트의 뷰
    83. 83. STAN (Structure Analysis for Java)STAN - http://stan4j.com/eclipse/eclipse-integration.html
    84. 84. Robert C. Martin의 그래프
    85. 85. Instability•패키지의 움직일 수 있는 여력을 판단하는지표•다른 패키지에 영향을 미치지 않고, 해당 패키지를 쉽게 변경 할 수 있는가?•Instability I = Ce / (Ca+Ce)•Ce = Efferent Coupling (Outgoing Dependencies)•Ca = Afferent Coupling (Ingoing Dependencies )
    86. 86. Instability Instability I = Ce / (Ca+Ce)당신의 패키지가 다른 사람이 많이 쓴다면,즉 Outgoing, Ce가 많다면, 여러분의 패키지는 변경하기 어렵다.반대로 Outgoing하는 Ce가 적다면, 여러분의 패키지는 쉽게 변경해도 된다.즉 0.0에서 0.3이면 안정적인 버전, 0.7에서 1.0이면 불안정적인 상태다
    87. 87. Abstractness Interface(Abstract) 와 Concrete Class를 비교A = (#abstract classes / total # of classes) •Abstract class = interface, abstract다 포함 •Total # class = abstract class + concrete class •0 이면 concrete class만 있다. •1 이면 abstract class만 있다.
    88. 88. 다시 보는 그래프 다른데서 많이 쓰는 녀석이니 조금 더 abstract를 높여야 돼!
    89. 89. 그 외 용어•Tangled Complexity •순환 참조가 있어 Boundary를 깰 때•Cyclomatic Complexity •분기 문이 많아 hotspot이 될 가망성이 높은 곳
    90. 90. 경고!!!환자의 외부 증상만고치는 의사가 되지 말자!!이러한 정보는 좋은 가이드일뿐!!숫자에 의존하다가오히려 아키텍쳐가 무너진다.
    91. 91. # 7. UI Patterns 다양한 안드로이드 UI 기법을 소개 http://bit.ly/QyDjMV
    92. 92. Android UI Pattern App 다양한 안드로이드 UI 기법을 오픈 소스로 공개http://bit.ly/QyDjMV
    93. 93. Android UI Pattern App
    94. 94. Android UI Pattern App
    95. 95. 예제 1 - android-actionbar
    96. 96. 스크린샷1 스크린샷2 XML 기능 Action Action예제 색변경
    97. 97. 스크린샷1 스크린샷2 XML 기능 Action Action예제 색변경
    98. 98. 스크린샷1 스크린샷2 XML 기능 Action Action예제 색변경
    99. 99. 스크린샷1 스크린샷2 XML 기능 Action Action예제 색변경
    100. 100. 스크린샷1 스크린샷2 XML 기능 Action Action예제 색변경
    101. 101. 스크린샷1 스크린샷2 XML 기능 Action Action예제 색변경
    102. 102. colors.xml 스크린샷1 스크린샷2 XML 기능 Action Action예제 색변경
    103. 103. 예제 2android-binding-frameworkhttp://code.google.com/p/android-binding/http://bit.ly/cxxwCF
    104. 104. Event에 대한 Binding다음과 같이 버튼에 대한 이벤트Method OnClick()
    105. 105. Main.xml
    106. 106. CalculateViewModel.java
    107. 107. Option.xml
    108. 108. Main Activity
    109. 109. Main Activity
    110. 110. Q &A
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×