대메뉴 바로가기 본문 바로가기

데이터 기술 자료

데이터 기술 자료 상세보기
제목 안드로이드 개발에 날개를 달자! : 생산성 높이는 라이브러리 모음집
등록일 조회수 6442
첨부파일  

안드로이드 개발에 날개를 달자!

생산성 높이는 라이브러리 모음집



자신이 만들 프로그램을 밑바닥부터 전부 다 만드는 개발자가 과연 있을까? 아마도 자신의 프로그램에 필요한 프레임워크를 선택하고 라이브러리를 추가한 뒤 중요한 로직만 개발할 것이다. 하지만 문제는 많은 사람이 좋은 라이브러리가 있음에도 그 존재를 몰라 직접 개발할 때가 있다는 것이다. 이번 시간에는 지난 시간에 이어 개발자들의 시간을 절약해 줄 강력한 안드로이드 라이브러리들을 소개한다.



지난 시간에 안드로이드 개발 생산성을 높일 유용한 안드로이드 스튜디오 플러그인을 소개했다. 플러그인을 도입하는 것만으로 충분히 생산성이 향상됐을 것이다. 이번 시간에는 개발자들의 수고를 덜어줄 강력한 안드로이드 라이브러리들을 소개한다.



안드로이드 스튜디오 Project 창에서 개발 중인 프로젝트를 선택하고 단축키 F4(맥은 + ↓)를 누르면 <그림 1>과 같이 Project Structure 창이 뜬다. 좌측에서 애플리케이션 모듈을 선택하고 Dependencies 탭을 누르면 좌측 하단에 추가, 삭제 아이콘이 표시되는 것을 볼 수 있다. 여기서 추가 아이콘을 누르면 첫 번째에 “1 Library dependency”가 표시된다. 바로 메이븐을 이용해 라이브러리를 추가하는 것이다.



앞서 본 “1 Library dependency” 버튼을 누르면 <그림 2>와 같은 창이 나타난다. 일반적으로 많이 사용되는 라이브러리들의 경우 메이븐을 이용해 쉽게 추가할 수 있다. 따라서 <그림 2>와 같은 창이 떴을 때 원하는 라이브러리를 검색해 추가하기만 하면 된다. 이 외에는 모듈 내에 있는 build.gradle 파일을 직접 수정한 후 설정해야 한다. 이와 관련해서는 뒤에 라이브러리들을 소개할 때 자세히 설명할 것이다. 참고로 이번 시간에 소개하는 라이브러리들의 예제를 필자의 깃허브(Github) 페이지(https://goo.gl/o0P3lI)에 올려놓았다.



EventBus

안드로이드 앱을 개발할 때 액티비티와 프래그먼트 또는 동일 프로세스상의 서비스와 통신해야 하는 경우가 종종 있다. 이 경우 대게 인터페이스로 리스너를 구현해 해결한다. 문제는 이를 위해 리스너를 정의하고 리스너 인스턴스를 관리하는 것에 손이 많이 간다는 것이다. EventBus는 이벤트 기반을 이용해 이런 수고를 덜어주는 라이브러리다.



<리스트 1> EventBus 설정 compile 'de.greenrobot:eventbus:2.4.0'



설치 방법은 메이븐 검색 창에서 “de.greenrobot:eventbus”를 검색한 뒤 추가하거나, build.gradle 파일의 dependencies 블록 안에 <리스트 1>과 같이 입력하면 된다.



<리스트 2> EventBus에서 사용할 이벤트 클래스 선언 public class MyEvent { }



EventBus를 사용하기 위해서는 먼저 이벤트 클래스를 선언해야 한다. 다만 이벤트 클래스라고 해서 특별한 클래스를 상속받아 사용하는 것은 아니고, 그냥 자신이 만들고 싶은 대로 클래스를 선언하면 된다. 여기서는 <리스트 2>와 같이 MyEvent라는 이벤트용 클래스를 선언했다.



<리스트 3> EventBus 인스턴스 선언 private EventBus mEventBus = EventBus.getDefault();



다음으로 <리스트 3>과 같이 EventBus의 인스턴스를 생성한다. 이벤트를 만드는 클래스나 이벤트를 수신하는 클래스 모두 이처럼 인스턴스를 생성해줘야 한다.



<리스트 4> 이벤트 생성 mEventBus.post(new MyEvent());



이벤트를 발생시킬 때는 post라는 메소드를 사용한다. 여기서 매개변수로 자신이 사용할 이벤트 클래스의 인스턴스를 넣는다. 여기서는 MyEvent 클래스에 속성이나 메소드를 사용하지 않았는데, 이벤트에 대한 추가적인 정보를 전달하고 싶은 경우에는 원하는 대로 속성과 메소드를 만들어 사용하면 된다.



<리스트 5> 이벤트 수신 관련 설정 //이벤트 수신 등록 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mEventBus.register(this); } //이벤트 수신 해제 @Override public void onDestroy() { mEventBus.unregister(this); super.onDestroy(); } //수신 이벤트 타입 선언 public void onEvent(MyEvent myEvent) { mTxtReceivedEvent.setText("Event is fired!!"); }



이벤트를 수신할 곳에서는 <리스트 5>와 같이 코드를 작성한다. 액티비티나 프래그먼트의 onCreate 함수 같은 곳에서 매개변수에 this를 넣고 register 메소드를 호출한다. 이처럼 호출하면 EventBus가 현재 클래스에서 이벤트와 관련된 함수가 선언돼 있는지 확인한다. 바로 onEvent 함수이다. 앞서 이벤트 클래스로 MyEvent를 생성했는데, 여기서 MyEvent 클래스를 수신하기 위해 onEvent 함수 매개변수에 MyEvent를 선언해 놓았다. 이에 따라 <리스트 4>가 실행되면 알아서 이 onEvent 함수가 실행된다. 이벤트를 수신할 필요가 없어지면 꼭 수신 해제를 해줘야 한다. 액티비티나 프래그먼트의 onDestroy 함수 같은 곳에서 this를 넣고 unregister 메소드를 호출한다.

주의할 점은 onEvent 함수는 <리스트 4>를 실행하는 스레드와 같은 스레드에서 실행된다. 따라서 UI 스레드와 관련된 작업을 한다면 <리스트 4>를 실행하는 스레드가 UI 스레드인지 아닌지 확인해야 한다.



android-logging-log4j

안드로이드 개발 시 로그를 확인하는 경우 대게 로그캣(logcat)을 사용한다. 하지만 로그캣은 오로지 PC와 연결이 된 경우에만 로그를 확인할 수 있다. android-logging-log4j는 로그를 안드로이드 기기 내 파일로 저장해주는 라이브러리다. 만약 사용자가 앱을 사용하다 에러가 나 충돌 보고서를 보내게 되는 경우 생성된 로그 파일을 보내도록 하면 앱의 문제점을 쉽게 찾아낼 수 있다. 설치 방법은 build.gradle 파일의 dependencies 블록 안에 <리스트 6>과 같이 입력하면 된다.



<리스트 6> android-logging-log4j 설정 compile 'log4j:log4j:1.2.+' compile 'de.mindpipe.android:android-logging-log4j:1.0.3'



<리스트 7> 외부 저장장치 쓰기 권한 설정 < uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />



외부 저장장치에 로그 파일을 생성하기 위해 AndroidManifest.xml 파일에 <리스트 7>과 같이 퍼미션(permission)을 추가한다.



<리스트 8> 로그 관련 설정 public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); LogConfigurator logConfigurator = new LogConfigurator(); logConfigurator.setFileName(Environment.getExternalStorageDirectory() + "/neosarchizo/Logs/logFile.log"); logConfigurator.configure(); } }



android-logging-log4j를 사용하는 경우 기존 log4j와 같이 log4j.properties, log4j.xml 설정 파일을 사용하지 않는다. 따라서 LogConfigurator를 이용해 설정해야 한다. 또한, 각 액티비티나 프래그먼트에서 매번 설정하는 것이 번거로울 수 있으므로 <리스트 8>과 같이 Applicaiton 클래스를 생성해 로그를 설정하도록 하는 것이 좋다. <리스트 8>에서는 간단히 로그 파일 경로만 설정했다. 만약 좀 더 다양한 설정을 원한다면 android-logging-log4j (https://goo.gl/U5w8Rg) 프로젝트 페이지를 참고하길 바란다.



<리스트 9> 로그 기록하기 public class MainActivity extends AppCompatActivity { private Logger mLogger = Logger.getLogger(MainActivity.class); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLogger.info("onCreate"); } }



로그를 기록할 때는 Logger 인스턴스를 생성해 기록하면 된다. 로그캣과 비슷하게 debug, info, error, warn과 같은 메소드들을 가지고 있다. 그리고 이 로그들은 파일로만 저장되는 것이 아니라 로그캣을 통해서도 표시된다. <리스트 9>는 MainActivity의 onCreate 함수가 실행될 때 로그 파일에 메시지가 기록되도록 한 것이다.



Picasso

최근 앱들을 살펴보면 웹에 있는 이미지를 기본적으로 사용한다. 그런데 이 웹에 있는 이미지를 사용할 때 처리를 안 해주면 화면이 늦게 뜬다거나 사용자 제어에 대한 반응이 지연될 수 있다. 웹에 있는 이미지가 아닌 로컬에 있는 큰 용량의 이미지를 사용할 때도 마찬가지다. 이와 관련해 구글에서 비동기로 이미지를 처리하는 예제(http://goo.gl/B6K500)를 제공하기도 한다. 하지만 예제처럼 하려면 코드가 상당히 지저분해질 수 있다. Picasso를 사용하면 이와 같은 문제를 아주 간단하게 처리할 수 있다.



<리스트 10> Picasso 설정 compile 'com.squareup.picasso:picasso:2.5.2'



설치 방법은 메이븐 검색 창에서 “com.squareup.picasso: picasso”를 검색한 뒤 추가하거나, build.gradle 파일의 dependencies 블록 안에 <리스트 10>과 같이 입력하면 된다.



<리스트 11> 인터넷 사용 권한 설정 < uses-permission android:name="android.permission.INTERNET" />



인터넷을 사용하기 위해 AndroidManifest.xml 파일에 <리스트 11>과 같이 퍼미션을 추가한다. 만약 단순히 로컬에 있는 데이터를 사용한다면 이 퍼미션을 추가하지 않아도 된다.



<리스트 12> Picasso 사용하기 Picasso.with(getApplicationContext()).load("http://i.imgur.com/DvpvklR.png").into(mImgView);



사용은 <리스트 12>와 같이 한다. with 메소드에 Context를, load 메소드에 불러올 이미지 Uri를, into에 ImageView를 넣어주면된다. 나머지는 알아서 Picasso 라이브러러가 처리해준다. ListView에서 사용하는 경우에도 해당 ImageView나 Holder의 ImageView를 매개 변수로 넣어주기만 하면 된다.



ButterKnife

기존 View와 Controller를 연결할 때 findViewById를 사용한다. 이때 연결하고자 할 View에 대한 변수를 로컬 또는 전역에 선언해야 한다. 문제는 이 연결하는 코드만으로 쉽사리 전체 코드가 지저분해질 수 있다는 것이다. ButterKnife는 간단한 어노테이션으로 View와 Controller를 쉽게 연결해주는 라이브러리다.



<리스트 13> ButterKnife 설정 compile 'com.jakewharton:butterknife:7.0.1'



설치 방법은 메이븐 검색 창에서 “com.jakewharton:butter knife”를 검색한 뒤 추가하거나, build.gradle 파일의 dependencies 블록 안에 <리스트 13>과 같이 입력하면 된다.



<리스트 14> ButterKnife 사용하기 @Bind(R.id.txtTitle) TextView txtTitle; @Bind({R.id.btnA, R.id.btnB, R.id.btnC}) List< Button> buttons; @OnClick(R.id.btnA) void button1() { Toast.makeText(this, "Hello!!", Toast.LENGTH_SHORT).show(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); txtTitle.setText("Hello~~~"); for (int i = 0; i < buttons.size(); i++) { buttons.get(i).setText("Button " + (i + 1)); } }



사용은 <리스트 14>와 같이 한다. 간혹 버전마다 어노테이션의 이름이 다르긴 하지만 사용방법은 동일하다. @Bind 어노테이션에 해당 View의 리소스 아이디를 설정하고 하단에 변수를 선언한다. setContentView와 같이 View를 초기화해주는 메소드 다음에 ButterKnife.bind 메소드를 호출하면 된다. 당연히 Holder에서도 사용할 수 있다. View를 배열로 선언하는 것도 가능하다. <리스트 14>와 같이 버튼들에 대한 리소스 아이디 배열을 넣고 하단에 배열 변수를 선언하는 것이다. 만약 버튼의 속성을 바꾸지 않고 단순히 Click 이벤트만 사용할 것이라면 @OnClick 어노테이션을 사용하면 된다.



Gson

Gson은 자바 객체를 JSON으로 그리고 JSON을 자바 객체로 변환해주는 라이브러리다. 요즘 서버와 통신하는 앱들의 경우 XML보다 JSON을 많이 사용한다. Gson을 사용하면 한 번의 파싱을 통해 JSON에서 곧바로 자바 객체를 얻을 수 있는 장점이 있다. 또한, 반대로 서버로 데이터 요청을 보낼 때도 해당 자바 객체를 JSON으로 간단히 변환할 수 있다. 아마 Gson을 직접 사용하기보다 사용하는 라이브러리가 Gson을 사용하는 경우가 많을 것이다. 뒤에 설명할 Retrofit이 그와 같은 예이다.



<리스트 15> Gson 설정 compile 'com.google.code.gson:gson:2.3.1'



설치 방법은 메이븐 검색 창에서 “com.google.code.gson:gson”를 검색한 뒤 추가하거나, build.gradle 파일의 dependencies 블록 안에 <리스트 15>와 같이 입력하면 된다.



<리스트 16> Gson에서 사용할 클래스 선언 public class Person { private String name; private String sex; private int age; @Override public String toString() { return "name : " + name + " sex : " + sex + " age : "+ age; } }



Gson을 사용하기 위해 클래스를 선언한다. 이때 <리스트 16>과 같이 자신이 원하는 대로 자유롭게 선언하면 된다.



<리스트 17> Gson 인스턴스 선언 Gson gson = new GsonBuilder().create();



다음으로 <리스트 17>과 같이 Gson의 인스턴스를 생성한다. 이 Gson 인스턴스를 이용해 JSON과 객체 간 변환을 한다. 인스턴스를 생성할 때 파싱과 관련된 옵션을 설정할 수도 있다. 예로 날짜를 어떤 포맷으로 변환할지 설정할 수도 있다.



<리스트 18> JSON에서 객체로 변환 person = gson.fromJson(txtJSON.getText().toString(), Person.class);



<리스트 18>은 JSON을 자바 객체로 변환하는 예다. 여기서 person은 Person형 변수이며, txtJSON이라는 TextView 안에 있는 JSON 데이터를 Person 객체로 바꾸는 것이다.



<리스트 19> 객체에서 JSON으로 변환 txtJSON.setText(gson.toJson(person));



<리스트 19>는 반대로 Person 객체를 JSON으로 변환하는 예다. 이 외에도 JSON 배열을 객체 배열로 변환, 객체가 멤버 변수로 있는 객체를 JSON으로 변환 등 다양한 것을 할 수 있다.



ActiveAndroid

Gson이 JSON과 객체간의 변환을 해주는 라이브러리라면 ActiveAndroid는 SQLite 데이터베이스 데이터와 객체를 서로 변환해주는 라이브러리다. 바로 ORM(objective relational mapper)이다.



<리스트 20> repositories 블록 설정 repositories { mavenCentral() maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } }



<리스트 21> ActiveAndroid 설정 compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'



설치 방법은 build.gradle 파일에 <리스트 20>과 같이 repositories 블록을 추가하고, <리스트 21>의 코드를 dependencies 블록 안에 넣어준다.



<리스트 22> AndroidManifest.xml 설정 < ?xml version="1.0" encoding="utf-8"?> < manifest xmlns:android="http://schemas.android.com/apk/res/android" package="kr.neosarchizo.activeandroid" > < application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:name="com.activeandroid.app.Application" android:theme="@style/AppTheme" > < meta-data android:name="AA_DB_NAME" android:value="Neosarchizo.db" /> < meta-data android:name="AA_DB_VERSION" android:value="1" /> < activity android:name=".MainActivity" android:label="@string/app_name" > < intent-filter> < action android:name="android.intent.action.MAIN" /> < category android:name="android.intent.category.LAUNCHER" /> < /intent-filter> < /activity> < /application> < /manifest>



AndroidManifest.xml 파일에도 <리스트 22>와 같이 설정을 해준다. application 태그의 name 속성을 "com.activeandroid.app.Application"으로 설정한다. 그리고 application 태그 안쪽 가장 윗부분에 name 속성이 각각 "AA_DB_NAME", "AA_DB_VERSION"으로 된 meta-data 태그들을 넣어준다. 이 태그들은 데이터베이스 파일 이름과 버전 정보를 나타내는 것이다.



<리스트 23> Category 데이터 관련 모델 클래스 @Table(name = "Categories") public class Category extends Model { @Column(name = "Name") public String name; }



<리스트 24> Items 데이터 관련 모델 클래스 @Table(name = "Items") public class Item extends Model { @Column(name = "Name") public String name; @Column(name = "Category") public Category category; }



마지막으로 모델 클래스를 설정해야 한다. <리스트 23>, <리스트 24>와 같이 ActiveAndroid의 Model을 상속받는 클래스를 선언한다. 이때 @Table 어노테이션이 해당 클래스가 저장될 데이터베이스의 테이블 명을, @Column 어노테이션이 해당 클래스의 테이블에 생성할 열을 뜻한다.



<리스트 25> ActiveAndroid 사용하기 Category restaurants = new Category(); restaurants.name = "Restaurants"; restaurants.save(); Item item = new Item(); item.category = restaurants; item.name = "Outback Steakhouse"; item.save(); item = new Item(); item.category = restaurants; item.name = "Olive Garden"; item.save(); List< Item> items = new Select().from(Item.class).execute(); for (Item i : items) Log.d("NEOSARCHIZO", "Item : "+ i.name + " ("+ i.category.name + ")"); new Delete().from(Item.class).execute();



사용법은 간단하다. <리스트 25>와 같이 일반 객체처럼 사용하면 된다. 단지 저장할 때 save 메소드만 호출하면 된다. <리스트 25>는 데이터를 생성한 뒤 전체 데이터를 로그캣에 찍은 후 데이터를 모두 삭제하는 코드이다. ActiveAndroid도 앞서 설명한 Gson과 함께 사용할 수 있다. 단, 그냥 사용할 시 에러가 난다.



<리스트 26> ActiveAndroid 모델 클래스에 Gson 관련 설정 @Table(name = "Items") public class Item extends Model { @Expose @Column(name = "Name") public String name; @Expose @Column(name = "Category") public Category category; }



<리스트 27> @Expose 어노테이션 관련 설정 Gson gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() .create();



만약 <리스트 24>와 같은 Model 클래스를 그대로 Gson에서 사용하는 경우 무수히 많은 에러가 발생할 것이다. 바로 Model 클래스에 기본적으로 있는 속성들 때문이다. 따라서 <리스트 26>과 같이 데이터로 사용하는 속성에만 @Expose 어노테이션을 붙여준다. 그리고 <리스트 27>과 같이 Gson 인스턴스를 생성할 때 excludeFieldsWithoutExposeAnnotation 메소드를 호출한다. 이렇게 하면 Gson이 @Expose 어노테이션이 붙은 속성만 JSON으로 생성한다. 이 경우 단순히 데이터베이스 데이터를 객체로만 변환하는 것이 아니라 손쉽게 JSON으로 변환할 수 있는 장점이 있다. 필자는 뒤에 설명할 Retrofit과 ActiveAndroid를 완전히 연결해 사용하기 때문에 이와 같은 설정을 해놓고 개발한다.



Retrofit

어찌 보면 Gson은 Retrofit을 설명하기 위해 소개한 것이라 할 수 있다. 바로 Retrofit이 Gson을 사용하기 때문에 기본적으로 Gson의 사용법을 알아야 한다. Retrofit은 앱과 서버 간의 API 통신을 쉽게 만들어주는 라이브러리다.



<리스트 28> Retrofit 설정 compile 'com.squareup.retrofit:retrofit:1.9.0'



설치 방법은 메이븐 검색 창에서 “com.squareup.retrofit”을 검색한 뒤 추가하거나, build.gradle 파일의 dependencies 블록 안에 <리스트 28>과 같이 입력하면 된다.



<리스트 29> 인터넷 사용 권한 설정 < uses-permission android:name="android.permission.INTERNET" />



서버와 통신하는 것이므로 당연히 <리스트 29>와 같이 Android Manifest.xml 파일에 퍼미션을 추가한다.



<리스트 30> API 경로 관리 클래스 public class Api { public final static String HOST = "https://raw.githubusercontent.com/ neosarchizo/BestAndroidLibraries/master/json"; public final static String USERS = "/users.json"; public final static String USER = "/user.json"; }



Retrofit을 사용하는 경우 <리스트 30>과 같이 API 경로만 관리하는 클래스를 생성한다. 꼭 Retrofit이 아니라도 API 통신을 하는 경우 습관적으로 이와 같이 하는 것이 좋다. 그리고 <리스트 30>에서와 같이 기본 도메인과 하위 경로를 분리한다. 여기서는 예제 때문에 부득이하게 USERS와 USER 경로로 필자의 깃허브 페이지에 JSON 파일 경로를 지정한 것이다. 실제 개발 시에는 자신의 API에 맞게 사용하면 된다.



<리스트 31> users.json [ { "name": "Junhyuk Lee", "password": "abcd" }, { "name": "Hyeonseong Lee", "password": "asdf" } ]



<리스트 32> user.json { "name": "Junhyuk Lee", "password": "abcd" }



<리스트 33> User 클래스 선언 public class User { String name, password; }



JSON 파일들은 <리스트 31>, <리스트 32>와 같이 구성돼 있다. Retrofit은 만약 서버로부터 이와 같은 JSON 데이터를 받으면 Gson을 이용해 객체로 변환한다. 이를 위해 <리스트 33>과 같이 클래스를 선언한다.



<리스트 34> API 인터페이스 선언 public interface MyAPI { @GET(Api.USER) void getUser(Callback< User> cb); @GET(Api.USER) User getUser(); @GET(Api.USERS) void getUsers(Callback< List< User>> cb); @GET(Api.USERS) List< User> getUsers(); }



다음은 API 인터페이스 선언이다. 앞서 Api 클래스가 단순히 경로만 관리했다면 실제 통신과 관련된 것이 이 인터페이스다. <리스트 34>를 보면 함수 반환형이 void와 User인 것을 볼 수 있는데, void는 콜백 방식, User는 동기화 방식을 뜻한다. 그런데 동기화 방식의 경우 일반 UI 스레드에서 사용할 때 앱이 강제 종료되기 때문에 될 수 있으면 콜백 방식을 사용하는 것이 좋다.



<리스트 35> Retrofit 사용하기 RestAdapter restAdapter = new RestAdapter.Builder().setEndpoint(Api.HOST).build(); MyAPI myAPI = restAdapter.create(MyAPI.class); //동기화 방식, UI 스레드에서 실행 시 앱이 강제 종료되니 Thread나 AsyncTask에서 사용한다. User user = myAPI.getUser(); //콜백 방식 myAPI.getUser(new Callback< User>() { @Override public void success(User user, Response response) { txtResponse.setText("name : " + user.name + " password : " + user.password); } @Override public void failure(RetrofitError error) { } });



사용법은 <리스트 35>와 같다. 먼저 RestAdapter 인스턴스를 이용해 API 인터페이스 인스턴스를 생성한다. 그리고 생성된 인터페이스 인스턴스의 메소드를 호출하기만 하면 된다. <리스트 35>는 사용자 정보에 해당하는 JSON을 읽어와 User 객체로 만들어주는 코드이다. 이렇게 Retrofit만으로도 상당히 멋진 라이브러리지만 ActiveAndroid와 함께 사용하면 아마 금상첨화라는 것을 느낄 것이다.



마무리하며

될 수 있는 대로 많은 것을 알려주고 싶어 글이 길어졌다. 그러나 이것도 각 라이브러리에 대해 아주 얕게 소개했을 뿐이다. 지면 관계상 자세히 소개하지 못한 내용이 더 많다. 미처 소개하지 못한 유용한 라이브러리들도 많다. 여유가 있을 때 AndroidView Animations(https://goo.gl/hVm7EG), cardslib(https://goo.gl/3H3Rt7) 라이브러리들을 한번 사용해보기 바란다. 이번 기고를 통해 많은 안드로이드 개발자들의 수고가 덜어지길 바란다.



출처 : 마이크로소프트웨어 10월호

제공 : 데이터 전문가 지식포털 DBguide.net