안드로이드 아키텍처 컴포넌트

2018. 12. 30. 16:42Android

반응형

안드로이드 팀이 제안하고 있는 것을 이해하기 위해, 우리는 구조 구성 요소의 모든 요소를 ​​알아야합니다. 왜냐하면 그것들은 우리를 위해 무거울 것입니다. RoomViewModelLiveData 및 Lifecycle의 4가지 구성 요소가 있습니다. 이러한 모든 부분에는 고유한 책임이 있으며, 함께 협력하여 견고한 아키텍처를 만듭니다. 더 잘 이해하기 위해 제안된 아키텍처의 단순화 된 다이어그램을 살펴 보겠습니다.

Android Architecture

보시다시피 세 가지 주요 요소가 있으며 각 요소는 책임이 있습니다.

  1. Activity 및 Fragment는 비즈니스 로직 및 복잡한 작업을 다루지 않는 View레이어를 나타냅니다. 뷰를 구성하고 사용자 상호 작용을 처리하며 가장 중요한 것은 ViewModel에서 가져온 LiveData 요소를 관찰하고 표시합니다.
  2. ViewModel은 구성 변경 및 기타 안드로이드 Lifecycle이벤트 동안 일관성을 유지하면서 뷰의 라이프 사이클 상태를 자동으로 관찰합니다. 또한 뷰에 의해 관찰 가능한 LiveData로 제공되는 Repository에서 데이터를 가져오는 것이 요구됩니다. ViewModel은 View를 직접 참조하지 않으며 데이터의 업데이트는 항상 LiveData 실재에 의해 수행된다는 것을 이해하는 것이 중요합니다.
  3. Repository는 특별한 안드로이드 구성 요소가 아닙니다. 특정 구현없이 간단한 클래스이며 데이터베이스에서 웹 서비스에 이르는 모든 사용 가능한 소스의 데이터를 가져옵니다. 이 모든 데이터를 처리하여 일반적으로 관찰 가능한 LiveData로 변환하여 ViewModel에서 사용할 수 있도록 합니다.
  4. Room 데이터베이스는 SQLite 매핑 라이브러리로서 데이터베이스 처리 프로세스를 용이하게 합니다. 자동으로 많은양의 상용구를 작성하고 컴파일 타임에 오류를 검사하며, 무엇보다 중요한 것은 관찰 가능한 LiveData가있는 쿼리를 직접 반환할 수 있다는 것입니다.

나는 당신이 우리가 관측 가능한 것들에 대해 많이 이야기한 것을 알아 차렸을 것입니다. 옵저버 패턴은 LiveData 요소 및 Lifecycle 인식 구성 요소의 기반 중 하나입니다. 이 패턴을 사용하면 객체가 관찰자 목록에 상태 나 데이터의 변경 사항을 알릴 수 있습니다. 따라서 Activity가 LiveData 의 실재를 관찰하면 해당 데이터가 어떤 종류의 수정을 거칠때 업데이트를 수신하게 됩니다.

또 다른 안드로이드 권장 사항은 Google의 Dagger 2와 같은 Dependency Injection 시스템을 사용하거나 DI보다 간단하지만 장점이없는 Service Locator패턴을 사용하여 아키텍처를 통합하는 것입니다. 이 튜토리얼에서는 DI 또는 Service Locator에 대해서는 다루지 않지만 Envato Tuts+에는 이러한 주제에 대한 훌륭한 자습서가 있습니다. 그러나이 시리즈의 두 번째 부분에서 설명 할 Dagger 2 및 안드로이드 구성 요소를 사용하는 데에는 몇 가지 특수성이 있습니다.

우리는 이 아키텍처 모델을 실제로 이해하고 채택할 수 있도록 새로운 구성 요소의 측면을 깊이 파고 들어야합니다. 그러나 이 튜토리얼에서는 모든 세부 사항을 다루지 않을 것입니다. 이 튜토리얼에서는 각 요소의 복잡성으로 인해 각 요소의 일반적인 개념에 대해서만 설명하고 간단한 코드 스니펫을 살펴 보겠습니다. 우리는 구성 요소를 제시하고 시작하도록 충분한 근거를 다룰 것입니다. 하지만 이 시리즈의 향후 기사에서는 아키텍처 구성 요소의 모든 특수성을 다룰 것이므로 두려워하지 않아야 합니다.

대부분의 안드로이드 앱 구성 요소에는 시스템에 직접 관리되는 라이프 사이클이 첨부되어 있습니다. 최근까지는 개발자가 구성 요소의 상태를 모니터링 하고 이에 따라 조치를 취하고 적절한 시기에 작업을 초기화하고 종료하는 것이 개발자의 몫이었습니다. 그러나 이 유형의 작업과 관련하여 혼란스러워 실수를 하는 것은 정말 쉽습니다. 그러나 android.arch.lifecycle 패키지가 이 모든 것을 변경했습니다.

이제 Activity 및 Fragments에는 LifecycleObserver 클래스에서 볼 수있는 Lifecycle 객체(예 : ViewModel 또는 이 인터페이스를 구현하는 객체)가 첨부되어 있습니다. 이는 관찰자가 활동이 일시 중지되거나 시작될 때와 같이 관찰중인 객체의 상태 변화에 대한 업데이트를 수신한다는 것을 의미합니다. 또한 관찰된 객체의 현재 상태를 확인할 수 있습니다. 따라서 프레임 워크 라이프 사이클을 고려해야하는 작업을 처리하는 것이 훨씬 쉽습니다.

LifecycleObserver reacts to LifecycleEvents

지금은이 새로운 표준을 준수하는 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 인스턴스화 중 Lifecycle을 제공 한 경우 LiveData는 Lifecycle 상태에 따라 작동합니다. 관찰자의 Lifecycle 상태가 STARTED 또는 RESUMED이면 관찰자가 active 상태입니다. 그렇지 않으면 inactive 상태입니다.

LiveData는 데이터가 변경된 시기와 관찰자가 active 되어 있고 업데이트를 받아야 하는지 알고 있습니다. LiveData의 또 다른 흥미로운 특징은 관찰자가 Lifecycle.State.DESTROYED 상태에 있는 경우 관찰자를 제거할 수 있다는 것입니다. 이는 활동 및 조각에서 관찰할 때 메모리 누수를 방지합니다.

LiveData value updating process

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은 UI와 관련된 데이터를 보유하고 화면 회전과 같은 구성 변경 중에 무결성을 유지하도록 설계되었습니다. ViewModel은 Repository와 대화하고 LiveData를 가져와 뷰에서 볼 수 있도록 사용할 수 있게합니다. ViewModel은 구성 변경 후 Repository를 새로 호출 할 필요가 없으므로 코드가 많이 최적화됩니다.

ViewModel is tight to UI Lifecycle

뷰 모델을 만들려면 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")
                }
        )
    }
}

안드로이드는 처음부터 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