2018. 12. 30. 16:42ㆍAndroid
안드로이드 팀이 제안하고 있는 것을 이해하기 위해, 우리는 구조 구성 요소의 모든 요소를 알아야합니다. 왜냐하면 그것들은 우리를 위해 무거울 것입니다. Room
, ViewModel
, LiveData
및 Lifecycle
의 4가지 구성 요소가 있습니다. 이러한 모든 부분에는 고유한 책임이 있으며, 함께 협력하여 견고한 아키텍처를 만듭니다. 더 잘 이해하기 위해 제안된 아키텍처의 단순화 된 다이어그램을 살펴 보겠습니다.
보시다시피 세 가지 주요 요소가 있으며 각 요소는 책임이 있습니다.
Activity
및Fragment
는 비즈니스 로직 및 복잡한 작업을 다루지 않는View
레이어를 나타냅니다. 뷰를 구성하고 사용자 상호 작용을 처리하며 가장 중요한 것은ViewModel
에서 가져온LiveData
요소를 관찰하고 표시합니다.ViewModel
은 구성 변경 및 기타 안드로이드Lifecycle
이벤트 동안 일관성을 유지하면서 뷰의 라이프 사이클 상태를 자동으로 관찰합니다. 또한 뷰에 의해 관찰 가능한LiveData
로 제공되는Repository
에서 데이터를 가져오는 것이 요구됩니다.ViewModel
은View
를 직접 참조하지 않으며 데이터의 업데이트는 항상LiveData
실재에 의해 수행된다는 것을 이해하는 것이 중요합니다.Repository
는 특별한 안드로이드 구성 요소가 아닙니다. 특정 구현없이 간단한 클래스이며 데이터베이스에서 웹 서비스에 이르는 모든 사용 가능한 소스의 데이터를 가져옵니다. 이 모든 데이터를 처리하여 일반적으로 관찰 가능한LiveData
로 변환하여ViewModel
에서 사용할 수 있도록 합니다.Room
데이터베이스는 SQLite 매핑 라이브러리로서 데이터베이스 처리 프로세스를 용이하게 합니다. 자동으로 많은양의 상용구를 작성하고 컴파일 타임에 오류를 검사하며, 무엇보다 중요한 것은 관찰 가능한LiveData
가있는 쿼리를 직접 반환할 수 있다는 것입니다.
나는 당신이 우리가 관측 가능한 것들에 대해 많이 이야기한 것을 알아 차렸을 것입니다. 옵저버 패턴은 LiveData
요소 및 Lifecycle
인식 구성 요소의 기반 중 하나입니다. 이 패턴을 사용하면 객체가 관찰자 목록에 상태 나 데이터의 변경 사항을 알릴 수 있습니다. 따라서 Activity가 LiveData
의 실재를 관찰하면 해당 데이터가 어떤 종류의 수정을 거칠때 업데이트를 수신하게 됩니다.
또 다른 안드로이드 권장 사항은 Google의 Dagger 2와 같은 Dependency Injection 시스템을 사용하거나 DI보다 간단하지만 장점이없는 Service Locator패턴을 사용하여 아키텍처를 통합하는 것입니다. 이 튜토리얼에서는 DI 또는 Service Locator에 대해서는 다루지 않지만 Envato Tuts+에는 이러한 주제에 대한 훌륭한 자습서가 있습니다. 그러나이 시리즈의 두 번째 부분에서 설명 할 Dagger 2 및 안드로이드 구성 요소를 사용하는 데에는 몇 가지 특수성이 있습니다.
3. 아키텍처 구성 요소
우리는 이 아키텍처 모델을 실제로 이해하고 채택할 수 있도록 새로운 구성 요소의 측면을 깊이 파고 들어야합니다. 그러나 이 튜토리얼에서는 모든 세부 사항을 다루지 않을 것입니다. 이 튜토리얼에서는 각 요소의 복잡성으로 인해 각 요소의 일반적인 개념에 대해서만 설명하고 간단한 코드 스니펫을 살펴 보겠습니다. 우리는 구성 요소를 제시하고 시작하도록 충분한 근거를 다룰 것입니다. 하지만 이 시리즈의 향후 기사에서는 아키텍처 구성 요소의 모든 특수성을 다룰 것이므로 두려워하지 않아야 합니다.
라이프 사이클-인식 구성 요소
대부분의 안드로이드 앱 구성 요소에는 시스템에 직접 관리되는 라이프 사이클이 첨부되어 있습니다. 최근까지는 개발자가 구성 요소의 상태를 모니터링 하고 이에 따라 조치를 취하고 적절한 시기에 작업을 초기화하고 종료하는 것이 개발자의 몫이었습니다. 그러나 이 유형의 작업과 관련하여 혼란스러워 실수를 하는 것은 정말 쉽습니다. 그러나 android.arch.lifecycle
패키지가 이 모든 것을 변경했습니다.
이제 Activity 및 Fragments에는 LifecycleObserver
클래스에서 볼 수있는 Lifecycle
객체(예 : ViewModel
또는 이 인터페이스를 구현하는 객체)가 첨부되어 있습니다. 이는 관찰자가 활동이 일시 중지되거나 시작될 때와 같이 관찰중인 객체의 상태 변화에 대한 업데이트를 수신한다는 것을 의미합니다. 또한 관찰된 객체의 현재 상태를 확인할 수 있습니다. 따라서 프레임 워크 라이프 사이클을 고려해야하는 작업을 처리하는 것이 훨씬 쉽습니다.
지금은이 새로운 표준을 준수하는 Activity
또는 Fragment
을 작성하려면 LifecycleActivity
또는 LifecycleFragment
를 확장해야 합니다. 그러나 안드로이드 팀이 이러한 새로운 도구를 프레임 워크와 완전히 통합하기 위해 항상 필요한 것은 아니기 때문일 수 있습니다.
1 2 3 4 5 6 7 | class MainActivity : LifecycleActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } } |
LifecycleObserver
는 Lifecycle
이벤트를 수신하고 주석을 통해 대응할 수 있습니다. 메소드 대체는 필요하지 않습니다.
01 02 03 04 05 06 07 08 09 10 11 | class MainActivityObserver : LifecycleObserver, AnkoLogger { @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun onResume() { info("onResume") } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) fun onPause() { info("onPause") } } |
LiveData
구성 요소
LiveData
구성 요소는 관찰할 수 있는 값을 포함하는 데이터 홀더입니다. 관찰자가 LiveData
인스턴스화 중 Lifecycle
을 제공 한 경우 LiveData
는 Lifecycle
상태에 따라 작동합니다. 관찰자의 Lifecycle
상태가 STARTED
또는 RESUMED
이면 관찰자가 active
상태입니다. 그렇지 않으면 inactive
상태입니다.
LiveData
는 데이터가 변경된 시기와 관찰자가 active
되어 있고 업데이트를 받아야 하는지 알고 있습니다. LiveData
의 또 다른 흥미로운 특징은 관찰자가 Lifecycle.State.DESTROYED
상태에 있는 경우 관찰자를 제거할 수 있다는 것입니다. 이는 활동 및 조각에서 관찰할 때 메모리 누수를 방지합니다.
LiveData
는 onActive
및 onInactive
메소드를 구현해야 합니다.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | class LocationLiveData(context: Context) : LiveData<Location>(), AnkoLogger, LocationListener { private val locationManager: LocationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager override fun onActive() { info("onActive") locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0f, this) } override fun onInactive() { info("onInactive") locationManager.removeUpdates(this) } // .... } |
LiveData
구성 요소를 관찰하려면 observer(LifecycleOwner, Observer<T>)를 호출해야 합니다.
1 2 3 4 5 6 7 8 9 | class MainActivity : LifecycleActivity(), AnkoLogger { fun observeLocation() { val location = LocationLiveData(this) location.observe(this, Observer { location -> info("location: $location") }) } } |
ViewModel
구성 요소
새로운 아키텍처 구성 요소 중 가장 중요한 클래스 중 하나인 ViewModel
은 UI와 관련된 데이터를 보유하고 화면 회전과 같은 구성 변경 중에 무결성을 유지하도록 설계되었습니다. ViewModel
은 Repository
와 대화하고 LiveData
를 가져와 뷰에서 볼 수 있도록 사용할 수 있게합니다. ViewModel
은 구성 변경 후 Repository
를 새로 호출 할 필요가 없으므로 코드가 많이 최적화됩니다.
뷰 모델을 만들려면 ViewModel
클래스를 확장합니다.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 | class MainActivityViewModel : ViewModel() { private var notes: MutableLiveData<List<String>>? = null fun getNotes(): LiveData<List<String>> { if (notes == null) { notes = MutableLiveData<List<String>>() loadNotes() } return notes!! } private fun loadNotes() { // do async operation to fetch notes } } |
뷰에서 액세스하려면 ViewProviders.of(Activity|Fragment) .get (ViewModel::class)
를 호출할 수 있습니다. 이 팩토리 메서드는, ViewModel
의 새로운 인스턴스를 돌려 주거나, 보존된 인스턴스를 적절히 가져옵니다.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 | class MainActivity : LifecycleActivity(), AnkoLogger { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val viewModel = ViewModelProviders.of(this) .get(MainActivityViewModel::class.java) viewModel.getNotes().observe( this, Observer { notes -> info("notes: $notes") } ) } } |
Room
구성 요소
안드로이드는 처음부터 SQLite를 지원했습니다; 그러나 작동 시키려면 많은 상용구를 작성해야 했습니다. 또한 SQLite는 POJO (평범한 Java 객체)를 저장하지 않았으며 컴파일 타임에 쿼리를 확인하지 않았습니다. 함께 이 문제를 해결하는 Room
이 옵니다! Java POJO를 유지하고, 쿼리를 객체로 직접 변환하고, 컴파일 타임에 오류를 확인하고, 쿼리 결과에서 LiveData
관측 값을 생성할 수 있는 SQLite 매핑 라이브러리입니다. Room
은 멋진 안드로이드 용 부가 기능이 포함된 객체 관계 매핑 라이브러리입니다.
지금까지 다른 ORM 안드로이드 라이브러리를 사용할 수있는 Room
의 대부분을 수행 할 수있었습니다. 그러나 이들 중 어느 것도 공식적으로 지원되지 않으며 가장 중요한 것은 LifeData
결과를 산출할 수 없다는 것입니다. Room
라이브러리는 제안된 안드로이드 아키텍처의 영구 레이어로 완벽하게 들어 맞습니다.
Room
데이터베이스를 만들려면 Java POJO, 쿼리 및 입출력 작업을 수행하는 @Dao
인터페이스, RoomDatabase
를 확장해야 하는 @Database
추상 클래스가 될 수 있는 @Entity
가 필요합니다.
1 2 3 4 5 6 7 | @Entity class Note { @PrimaryKey var id: Long? = null var text: String? = null var date: Long? = null } |
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | @Dao interface NoteDAO { @Insert( onConflict = OnConflictStrategy.REPLACE ) fun insertNote(note: Note): Long @Update( onConflict = OnConflictStrategy.REPLACE ) fun updateNote(note: Note): Int @Delete fun deleteNote(note: Note): Int @Query("SELECT * FROM note") fun findAllNotes(): LiveData<Note> // on Kotlin the query arguments are renamed // to arg[N], being N the argument number. // on Java the arguments assume its original name @Query("SELECT * FROM note WHERE id = :arg0") fun findNoteById(id: Long): LiveData<Note> } |
1 2 3 4 | @Database( entities = arrayOf(Note::class), version = 1) abstract class Databse : RoomDatabase() { abstract fun noteDAO(): NoteDAO } |
프로젝트에 아키텍처 구성 요소 추가하기
지금은 새로운 아키텍처 구성 요소를 사용하려면 먼저 build.gradle
파일에 Google 저장소를 추가해야 합니다. 자세한 내용은 공식 가이드를 참조하십시오.
1 2 3 4 5 6 7 | allprojects { repositories { jcenter() // Add Google repository maven { url 'https://maven.google.com' } } } |
[출처 : https://code.tutsplus.com/ko/tutorials/introduction-to-android-architecture--cms-28749]
'Android' 카테고리의 다른 글
안드로이드 파이 대응 관련 (0) | 2019.04.18 |
---|---|
android-design-support-library (0) | 2019.04.18 |
roulette(룰렛) (0) | 2018.11.06 |
Lock Pattern (0) | 2018.11.06 |
FingerPrint(지문인증) (0) | 2018.11.06 |