https://developer.android.com/topic/libraries/architecture/adding-components.html
아키텍처 콤포넌트 소개 영상
LiveData - LiveData는 옵저버 패턴의 Data holder 이다. Data가 변경될 때 Observer를 통해 감지 할 수 있으며, 이를 통해 UI를 업데이트 할 수 있다.
이전 포스팅인 Room Database에 LiveData를 사용 할 수 있다. 간단하게 LiveData를 살펴본 뒤 느낀 부분은 LiveData 는 Reactive + Object 라는 느낌이었다. Reactive X의 Subject와 같은 Observable 를 정의된 Object ( LiveData<T> ) 가 기본적으로 갖고 있으며 , LiveData의 API를 통해 Object의 값을 변경하고, 변경 되었을 때 LiveData에 등록된 Observer 를 통하여 값의 변경을 감지 할 수 있다.
이전 포스팅의 RoomDatabase를 구현한 MemoDatabase를 보면 LiveData를 RxJava의 Completable 처럼 사용 한 것을 확인 할 수 있다.
Android MVVM 패턴을 위한 Architecture Components library - ROOM #1
private final MutableLiveData<Boolean> mIsDatabaseCreated = new MutableLiveData<>();
위와 비슷한 예제가 영상에 다이어그램으로 표시 되는데 간단한 개념은 아래 와 같다.
LiveData는 데이터가 변경되면 알려준다
기존 UI에는 Thursday 라는 요일이 표시되어 있고, Data에서는 Friday가 준비되어 있다.
Friday가 Mutable LiveData에 저장되면 UI에서 등록시킨 Observer가 데이터 변화를 감지하고 Notification을 받는다.
위 다이어그램 코드로 표현하면 아래와 같다
1 2 3 4 5 6 7 | String format = "%s is a good day for a hike."; message.setText(String.format(format, "Thursday")); MutableLiveData<String> dayOfWeek = new MutableLiveData<>(); dayOfWeek.observe(this, s -> { message.setText(String.format(format, s)); }); dayOfWeek.postValue("Friday"); | cs |
LiveData는 Lifecycle(생명주기) 를 알고있다.
Lifecycle Owners - Activities, Fragments
1 2 3 4 5 6 7 8 9 | public interface LifecycleOwner { /** * Returns the Lifecycle of the provider. * * @return The lifecycle of the provider. */ @NonNull Lifecycle getLifecycle(); } | cs |
기본으로 상속 받는 V7 library의 AppCompatActivity 가 LifecycleOwner이다.
꼭 Activity가 아니더라도 생명주기를 갖을 수 있는 특정 객체에 LifecycleOwner를 구현한다면, 구현된 객체 내에서도 LiveData를 사용 할 수 있지 않을까 생각해본다.
Lifecycle Observers - Interface LifecycleObserver ( LiveData )
1 | public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer); | cs |
Dao에서의 LiveData 사용 - 기존 List<T>를 LiveData<List<T>>로 변경
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Dao public interface ProductDao{ @Insert(onConflict = IGNORE) void insert(ProductEntity data); @Insert(onConflict = IGNORE) void insertAll(List<ProductEntity> data); @Query("SELECT * From ProductEntity") List<ProductEntity> findAll(); @Update(onConflict = REPLACE) void update(ProductEntity data); @Query("DELETE FROM ProductEntity") void deleteAll(); } | cs |
이전 포스팅에서 정의 하였던 ProductDao 이다. 위 List<ProductEntity>를 LiveData로 바꿔보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Dao public interface ProductDao{ @Insert(onConflict = IGNORE) void insert(ProductEntity data); @Insert(onConflict = IGNORE) void insertAll(List<ProductEntity> data); @Query("SELECT * From ProductEntity") LiveData<List<ProductEntity>> findAll(); @Update(onConflict = REPLACE) void update(ProductEntity data); @Query("DELETE FROM ProductEntity") void deleteAll(); } | cs |
교체 완료!
그럼 이전 포스팅에서 사용했던 테스트 코드를 간단하게 재활용하여 동작시켜 보자.
Android Test
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | @RunWith(AndroidJUnit4.class) public class ProductDaoTest { private static final String TAG = "ProductDaoTest"; Context context; ProductDao mProductDao; @Before public void createDb() { context = InstrumentationRegistry.getTargetContext(); mProductDao = MemoDatabase.getInstance(context).productDao(); } @Test public void insertAndRead() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); mProductDao.deleteAll(); mProductDao.insert(makeProduct("Apple", "Apple.co.kr")); LiveData<List<ProductEntity>> liveProductList = mProductDao.findAll(); liveProductList.observeForever(productEntities -> { Log.d(TAG, "IN Observe!!!! CHANGE PRODUCT" + productEntities); }); Log.d(TAG, "ALL PRODUCT" + liveProductList); mProductDao.insert(makeProduct("Windows", "Microsoft.co.kr")); latch.await(1, TimeUnit.SECONDS); mProductDao.insert(makeProduct("Mouse", "Mickey")); latch.await(1, TimeUnit.SECONDS); } @After public void closeDb(){ MemoDatabase.getInstance(context).close(); } public ProductEntity makeProduct(String name, String store){ Log.d(TAG, "makeProduct() called with: name = [" + name + "], store = [" + store + "]"); ProductEntity product = new ProductEntity(); product.setId(UUID.randomUUID().toString()); product.setCheckInDate(0); product.setCheckOutDate(0); product.setName(name); product.setStoreName(store); return product; } } | cs |
LiveData에 observer를 등록 후 Product Data를 Insert 할 때 마다 등록된 Observer를 통해 변경된 전체 Product List를 전달 받는 것을 확인 할 수 있다.
정리 - 기존에 등록된 DB Update Observable 들을 LiveData로 변경 가능하다!
'개발 > 안드로이드' 카테고리의 다른 글
안드로이드 API 27 풀스크린 모드 ( Full screen mode ) 주의 사항 (0) | 2018.05.10 |
---|---|
AudioManager를 그냥 사용하면 메모리 누수 (Memory leak) 이 발생한다 (0) | 2018.03.27 |
Android MVVM 패턴을 위한 Architecture Components library - ROOM #1 (0) | 2017.11.19 |
알아두면 좋은 Android Studio Live templates (0) | 2017.09.29 |
Nexsus & Pixel 시리즈 안드로이드 O ( 8.0 버전, API 26 ) 업데이트 (0) | 2017.09.14 |