Slide 1

Slide 1 text

Android Architecture Components ֢അࢳ @pluulove Yanolja Android Developer GDG Korea Android organizer

Slide 2

Slide 2 text

Lifecycle

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

ࣛ૒ೠ ब੿ ୹୊ ~ ۨ૓௏޸झ : ۨ߄ొ

Slide 7

Slide 7 text

Data L i f e c y c l e ۄ੉೐ࢎ੉௿੄ ߷

Slide 8

Slide 8 text

Android Architecture Components

Slide 9

Slide 9 text

Handling Lifecycles LiveData ViewModel Room

Slide 10

Slide 10 text

୭ઙ ইఃఫ୊ ഋక

Slide 11

Slide 11 text

୭ઙ ইఃఫ୊ ഋక Clean Architecture 
 + MVVM 
 + Lifecycle

Slide 12

Slide 12 text

Handling Lifecycles

Slide 13

Slide 13 text

Lifecycle States and Events

Slide 14

Slide 14 text

class MyActivity extends AppCompatActivity {
 private MyLocationListener myLocationListener;
 
 public void onCreate(...) {
 myLocationListener = new MyLocationListener(this, (location) -> {
 // update UI
 });
 }
 
 public void onStart() {
 super.onStart();
 myLocationListener.start();
 }
 
 public void onStop() {
 super.onStop();
 myLocationListener.stop();
 }
 } ࢤݺ઱ӝ ҙ۲ ੌ߈੸ੋ Android ࢸ҅ ● onStart()ীࢲ द੘ ● onStop()ীࢲ ઙܐ

Slide 15

Slide 15 text

Handling Lifecycles Lifecycle LifecycleOwner LifecycleObserver

Slide 16

Slide 16 text

Lifecycle ࢤݺ ઱ӝ ੉߮౟੄ ৌѢഋҗ ೣԋ അ੤ ࢤݺ ઱ӝ ࢚క੄ ৌѢഋਸ ࢎਊೞৈ ҙ۲ ҳࢿ ਃࣗী ؀ೠ ࢤݺ ઱ӝ ࢚కܳ ୶੸

Slide 17

Slide 17 text

LifecycleOwner Lifecycle ё୓ܳ ߈ജೞח ױੌ ੋఠಕ੉झ ݫࢲ٘ী ઱ࢳਸ ୶оೣਵ۽ॄ ҳࢿ ਃࣗ੄ ࢤݺ ઱ӝ ੉߮౟ܳ ݽפఠ݂ೡ ࣻ ੓ח ੋఠಕ੉झ LifecycleObserver

Slide 18

Slide 18 text

public class LifecycleActivity extends FragmentActivity implements LifecycleRegistryOwner {
 private final LifecycleRegistry mRegistry = new LifecycleRegistry(this); 
 @Override
 public LifecycleRegistry getLifecycle() {
 return mRegistry;
 }
 } 
 
 public class LifecycleFragment extends Fragment implements LifecycleRegistryOwner {
 LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
 
 @Override
 public LifecycleRegistry getLifecycle() {
 return mLifecycleRegistry;
 }
 }

Slide 19

Slide 19 text

will be deprecated LifecycleActivity LifecycleFragment Architecture Components ח അ੤ ঌ౵ ߡ੹ Fragmentҗ AppCompatActivity۽ח ҳഅ ࠛоמ Lifecycles ೐۽ં౟о ୹दغݶ Support Library Fragment৬ Activityо LifecycleOwner ੋఠಕ ੉झܳ ҳഅೠ׮.

Slide 20

Slide 20 text

public class MyObserver implements LifecycleObserver {
 public MyObserver(Lifecycle lifecycle) {
 // Starts lifecycle observation
 lifecycle.addObserver(this);
 ...
 }
 
 // Annotated methods called when the associated lifecycle goes through these events
 @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
 public void onResume() {
 }
 @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
 public void onPause() {
 }
 }
 MyObserver observer = new MyObserver(aLifecycleOwner.getLifecycle()); 1 2 4 3

Slide 21

Slide 21 text

implements LifecycleObserver
 @OnLifecycleEvent(Lifecycle.Event.ON_START) APT ח GenericLifecycleObserver / ReflectiveGenericLifecycleObserver (ղࠗ ௿ېझ ਊ) ী ೯زਸ ੹׳ Lifecycle#State ߸ച ١ਸ LifecycleObserverী Dispatch Lifecycle Flow APTী ੄೧ 
 
 ${Activity_name}
 _${LifecycleObserver_name}
 _LifecycleAdapter 
 
 ௿ېझо ࢤࢿؽ

Slide 22

Slide 22 text

ViewModel UI ҙ۲ ؘ੉ఠܳ ੷੢ೞҊ ҙܻೞৈ ؘ੉ఠо ച ݶ ഥ੹җ э਷ ҳࢿ ߸҃ਸ Ѽ٧ ࣻ ੓ب۾ ࢸ҅غ ঻णפ׮.

Slide 23

Slide 23 text

ViewModel ଼੐ UI ؘ੉ఠ ҙܻ Activity / Fragment ߂ աݠ૑ জ ࢎ੉੄ ాन ୊ܻ Configuration ߸҃ী ؀਽ೞח ؘ੉ఠ ੷ ੢ Activity / Fragment ۽ࠗఠ ة݀

Slide 24

Slide 24 text

The lifecycle of a ViewModel : https://developer.android.com/topic/libraries/architecture/viewmodel.html ViewModel Scope ViewModelਸ о૑ח Activityо ઙ ܐغח ҃਋, ೐ۨ੐ਕ௼о ViewModel੄ onClearedܳ ഐ୹ೣ

Slide 25

Slide 25 text

https://github.com/googlecodelabs/android-lifecycles/blob/master/app/src/main/java/com/example/android/lifecycles/step2/ChronometerViewModel.java public class ChronometerViewModel extends ViewModel {
 
 @Nullable
 private Long startDate;
 
 @Nullable
 public Long getStartDate() {
 return startDate;
 }
 
 public void setStartDate(final long startDate) {
 this.startDate = startDate;
 }
 }

Slide 26

Slide 26 text

https://github.com/googlecodelabs/android-lifecycles/blob/master/app/src/main/java/com/example/android/lifecycles/step2/ChronoActivity2.java public class ChronoActivity2 extends LifecycleActivity {
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 ...
 ChronometerViewModel chronometerViewModel
 = ViewModelProviders.of(this).get(ChronometerViewModel.class);
 ...
 }
 } ViewModelProviders.of(this) ܳ ખ ؊ Ө੉ ଺ইࠁݶ, ViewModel਷ UI (Activity / Fragment)৬ োѾغয ੓਺ਸ ঌ ࣻ ੓णפ׮.

Slide 27

Slide 27 text

ViewModelProviders ViewModelStore੄ ਬ౰ܻ౭ ௿ېझ ղࠗ੸ਵ۽ ViewModelStoreܳ ଵઑೞৈ ViewModel੄ ӝઓ ੋ झఢझܳ ߈ജ, ઓ੤ೞ૑ ঋח ҃਋ ViewModel ੋझఢझܳ ࢜۽ ੘ࢿ೤פ׮.

Slide 28

Slide 28 text

android.arch.lifecycle.ViewModelStores.java public class ViewModelStore {
 
 private final HashMap mMap = new HashMap<>();
 
 final void put(String key, ViewModel viewModel) {
 ViewModel oldViewModel = mMap.get(key);
 if (oldViewModel != null) {
 oldViewModel.onCleared();
 }
 mMap.put(key, viewModel);
 }
 
 final ViewModel get(String key) {
 return mMap.get(key);
 }
 
 public final void clear() {
 for (ViewModel vm : mMap.values()) {
 vm.onCleared();
 }
 mMap.clear();
 }
 }

Slide 29

Slide 29 text

ViewModel ীࢲ ApplicationContext о ೙ਃೠ ҃਋? AndroidViewModel ܳ ੉ਊ

Slide 30

Slide 30 text

android.arch.lifecycle.AndroidViewModel.java public class AndroidViewModel extends ViewModel {
 private Application mApplication;
 
 public AndroidViewModel(Application application) {
 mApplication = application;
 }
 
 /**
 * Return the application.
 */
 public T getApplication() {
 return (T) mApplication;
 }
 }

Slide 31

Slide 31 text

ViewModel ઁড Viewী ૒੽ ੽Ӕ X Drawable ١ Resource о૗ X Activity / Fragment о૗ X ઙܐद੄ ୊ܻח onCleared()ী ӝࣿ

Slide 32

Slide 32 text

ViewModelsח UIীࢲ ؘ੉ఠܳ ࠙ ܻೞחؘ ݒ਋ ਬਊ

Slide 33

Slide 33 text

LiveData ч (Value Holder)ਸ ࠁਬೞҊ ч੄ ߸҃ ࢎ೦ਸ ҙ଴ ೡ ࣻ੓ח ҳࢿ ਃࣗੑפ׮. ViewHolder੄ ؘ੉ఠܳ ਬ૑ೞب۾ ࢸ҅

Slide 34

Slide 34 text

LiveData ч (Value Holder)ਸ ࠁਬೞҊ ч੄ ߸҃ ࢎ೦ਸ ҙ଴ ೡ ࣻ੓ח ҳࢿ ਃࣗੑפ׮. ViewHolder੄ ؘ੉ఠܳ ਬ૑ೞب۾ ࢸ҅ Observableೠ DataHolder

Slide 35

Slide 35 text

LiveData ੢੼ ೦࢚ ୭न ؘ੉ఠ ੸੺ೠ ҳࢿ ߸҃ ݫݽܻ ־ࣻ হ਺ (Lifecycle) Lifecycle੉ উ੹ೡदী݅ ੹׳ ч ߸҃ ୓௼ܳ ਤೠ ߹ب ҳഅ X

Slide 36

Slide 36 text

LiveData ৬ ӝઓҗ੄ ର੉ EventBus RxJava BehaviorSubject Lifecycle੉ উ੹ೠ ࢚కੌٸ݅ ా૑о מ ೠߣ ҳةೞݶ ੗زਵ۽ ೧ઁ೧ષ

Slide 37

Slide 37 text

https://codelabs.developers.google.com/codelabs/android-persistence/index.html?index=..%2F..%2Fio2017#5 mViewModel.books.observe(this, new Observer>() {
 @Override
 public void onChanged(@NonNull final List books) {
 showBooksInUi(books, mBooksTextView);
 }
 }); Model ߸҃द ഐ୹ Model ҙ଴ update UI

Slide 38

Slide 38 text

Android Architecture Components : https://cdn-images-1.medium.com/max/800/1*monWnJky1B9cAtvniFM39w.png LifecycleObserver

Slide 39

Slide 39 text

LiveData ా૑ दӝ LiveData#setValue(...) LiveData#postvalue(...) Active ࢚కীࢲ LiveData ч੉ ߸҃غ ঻ਸ ٸ Inactiveীࢲ Active о غ঻ਸ ٸ

Slide 40

Slide 40 text

Room

Slide 41

Slide 41 text

Room SQLite੄ ୶࢚ ۨ੉যܳ ઁҕೞৈ SQLite੄ ݽٚ ӝמਸ ഝਊೞݶࢲ ؘ੉ఠ߬੉झ ঘࣁझܳ ೲਊ

Slide 42

Slide 42 text

਺... ୹୊ ~ ۨ૓௏޸झ : ۨ߄ొ

Slide 43

Slide 43 text

Room = SQLiteਸ ਤೠ 
 Retrofit э਷ ו՝

Slide 44

Slide 44 text

Room ੢੼ Object Mapping Library ਗद SQL ௪ܻ੄ ஹ౵ੌ ఋ੐ Ѩૐ SQL ௪ܻ৬ Java ؘ੉ఠ ё୓ ࢎ੉ܳ ߸ജೞח boilerplate codeܳ ઁѢ ழࢲ ژח ۽؊ ੘ࢿ ೙ਃ হ਺ ߈ജ ૑ਗೣ ؘ੉ఠ ৔ࣘച ઁҕ

Slide 45

Slide 45 text

https://github.com/googlecodelabs/android-persistence/blob/master/app/src/main/java/com/example/android/persistence/codelab/db/User.java @Entity
 public class User {
 @PrimaryKey public String id;
 public String name;
 public String lastName;
 public int age; @Ignore
 Bitmap picture; } Entity ● @PrimaryKey ӝࠄః ૑੿ ○ autoGenerate ○ primaryKeys ○ tableName ● @Ignore ૑੿ೠ ೙٘ח Column ࢤࢿ୊ܻܳ ೞ૑ ঋ ਺ ● setter/getterܳ ੉ਊ೧ ೙٘ ੽Ӕ ● @ColumnInfo ߹ب ૑੿ оמ

Slide 46

Slide 46 text

https://github.com/googlecodelabs/android-persistence/blob/master/app/src/main/java/com/example/android/persistence/codelab/db/Loan.java @Entity(foreignKeys = {
 @ForeignKey(entity = Book.class,
 parentColumns = "id", childColumns = "book_id"),
 @ForeignKey(entity = User.class,
 parentColumns = "id", childColumns = "user_id")})
 @TypeConverters(DateConverter.class)
 public class Loan {
 public @PrimaryKey String id;
 public Date startTime;
 public Date endTime;
 @ColumnInfo(name="book_id")
 public String bookId;
 @ColumnInfo(name="user_id")
 public String userId;
 } Foreign Key

Slide 47

Slide 47 text

https://github.com/googlesamples/android-architecture-components/blob/178fe541643adb122d2a8925cf61a21950a4611c/BasicSample/app/src/main/java/com/example/ android/persistence/db/converter/DateConverter.java public class DateConverter {
 @TypeConverter
 public static Date toDate(Long timestamp) {
 return timestamp == null ? null : new Date(timestamp);
 }
 
 @TypeConverter
 public static Long toTimestamp(Date date) {
 return date == null ? null : date.getTime();
 }
 } TypeConverter ੑ۱ ఋੑ DB ীࢲ੄ ఋੑ ୹۱ ఋੑ Date Long Date

Slide 48

Slide 48 text

https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/main/java/com/android/example/github/vo/ Repo.java @Entity(primaryKeys = {"name", "owner_login"})
 public class Repo {
 public final int id;
 @SerializedName("name")
 public final String name;
 @SerializedName("full_name")
 public final String fullName;
 ...
 @SerializedName("owner")
 @Embedded(prefix = "owner_")
 public final Owner owner;
 ...
 } Nested Objects public class Owner {
 @SerializedName("login")
 public final String login;
 @SerializedName("url")
 public final String url;
 ...
 }

Slide 49

Slide 49 text

Nested Objects ~ Example

Slide 50

Slide 50 text

Nested Objects ѐ୓ী ೞਤ ೙٘۽ ࠙೧ೞৈ ё୓ܳ ಴അ Room਷ Entityр੄ ҙ҅ܳ য়࠳ં౟۽ ಴അ ࠛ оמ RDBܳ ਤೠ ۨ੉য੉ݶࢲ Object-relational mapping ੉ ইצ ੉ਬ class A { 
 @OneToOne // ૑ਗ ࠛо
 public B b;
 }

Slide 51

Slide 51 text

https://github.com/googlecodelabs/android-persistence/blob/master/app/src/main/java/com/example/android/persistence/codelab/db/UserDao.java @Dao
 public interface UserDao {
 @Query("select * from user")
 List loadAllUsers();
 
 @Query("select * from user where name = :firstName and lastName = :lastName")
 List findByNameAndLastName(String firstName, String lastName);
 
 @Delete
 void deleteUser(User user);
 
 @Insert(onConflict = IGNORE)
 void insertOrReplaceUsers(User... users);
 ...
 } Data Access Object (Dao)

Slide 52

Slide 52 text

https://github.com/googlecodelabs/android-persistence/blob/master/app/src/main/java/com/example/android/persistence/codelab/db/UserDao.java @Dao
 public interface UserDao {
 @Query("select * from user")
 List loadAllUsers();
 
 @Query("select * from user where name = :firstName and lastName = :lastName")
 List findByNameAndLastName(String firstName, String lastName);
 
 @Delete
 void deleteUser(User user);
 
 @Insert(onConflict = IGNORE)
 void insertOrReplaceUsers(User... users);
 ...
 } Data Access Object (Dao)

Slide 53

Slide 53 text

public List findByNameAndLastName(String firstName, String lastName) {
 final String _sql = "select * from user where name = ? and lastName = ?";
 final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 2);
 int _argIndex = 1;
 if (firstName == null) {
 _statement.bindNull(_argIndex);
 } else {
 _statement.bindString(_argIndex, firstName);
 }
 _argIndex = 2;
 if (lastName == null) {
 _statement.bindNull(_argIndex);
 } else {
 _statement.bindString(_argIndex, lastName);
 } UserDao_Impl implements UserDao (1/3)

Slide 54

Slide 54 text

final Cursor _cursor = __db.query(_statement);
 try {
 final int _cursorIndexOfId = _cursor.getColumnIndexOrThrow("id");
 final int _cursorIndexOfName = _cursor.getColumnIndexOrThrow("name");
 final int _cursorIndexOfLastName = _cursor.getColumnIndexOrThrow("lastName");
 final int _cursorIndexOfAge = _cursor.getColumnIndexOrThrow("age");
 final List _result = new ArrayList(_cursor.getCount());
 while(_cursor.moveToNext()) {
 final User _item;
 _item = new User();
 _item.id = _cursor.getString(_cursorIndexOfId);
 _item.name = _cursor.getString(_cursorIndexOfName);
 _item.lastName = _cursor.getString(_cursorIndexOfLastName);
 _item.age = _cursor.getInt(_cursorIndexOfAge);
 _result.add(_item);
 } return _result; UserDao_Impl implements UserDao (2/3)

Slide 55

Slide 55 text

} finally {
 _cursor.close();
 _statement.release();
 }
 } UserDao_Impl implements UserDao (3/3)

Slide 56

Slide 56 text

https://github.com/googlecodelabs/android-persistence/blob/master/app/src/main/java/com/example/android/persistence/codelab/db/AppDatabase.java // Create Database
 @Database(entities = {User.class, Book.class, Loan.class}, version = 1)
 public abstract class AppDatabase extends RoomDatabase {
 public abstract UserDao userModel();
 public abstract BookDao bookModel();
 public abstract LoanDao loanModel();
 ...
 } Database

Slide 57

Slide 57 text

public class AppDatabase_Impl extends AppDatabase {
 private volatile UserDao _userDao;
 private volatile BookDao _bookDao;
 private volatile LoanDao _loanDao;
 
 protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration configuration) {
 // Create, Drop, Migration … etc
 } @Override protected InvalidationTracker createInvalidationTracker() { ... }
 @Override public UserDao userModel() { … }
 @Override public BookDao bookModel() { … }
 @Override public LoanDao loanModel() { … }
 } AppDatabase_Impl extends AppDatabase (1/3) // ప੉࠶ ߸҃ਸ х૑

Slide 58

Slide 58 text

protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration configuration) {
 final SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(configuration, new RoomOpenHelper.Delegate() {
 public void createAllTables(SupportSQLiteDatabase _db) { … }
 public void dropAllTables(SupportSQLiteDatabase _db) { … }
 protected void onCreate(SupportSQLiteDatabase _db) { … }
 public void onOpen(SupportSQLiteDatabase _db) { … }
 protected void validateMigration(SupportSQLiteDatabase _db) { … }
 }, "..."); AppDatabase_Impl extends AppDatabase (2/3)

Slide 59

Slide 59 text

final SupportSQLiteOpenHelper.Configuration _sqliteConfig = SupportSQLiteOpenHelper.Configuration.builder(configuration.context)
 .name(configuration.name)
 .version(1)
 .callback(_openCallback)
 .build();
 final SupportSQLiteOpenHelper _helper = configuration.sqliteOpenHelperFactory.create(_sqliteConfig);
 return _helper;
 } AppDatabase_Impl extends AppDatabase (3/3)

Slide 60

Slide 60 text

https://github.com/googlecodelabs/android-persistence/blob/master/app/src/main/java/com/example/android/persistence/codelab/db/AppDatabase.java // Use Room Database
 AppDatabase db = Room.inMemoryDatabaseBuilder( context.getApplicationContext(), AppDatabase.class)
 .allowMainThreadQueries()
 .build(); Use Database

Slide 61

Slide 61 text

https://developer.android.com/reference/android/arch/persistence/room/Room.html // File
 Builder databaseBuilder (Context context,
 Class klass, String name)
 // Memory Builder inMemoryDatabaseBuilder (Context context,
 Class klass) Database Generate Options

Slide 62

Slide 62 text

Invalidation Tracker ۨ௏٘ ߸҃ী ؀ೠ ୶੸ InvalidationTracker ௿ېझо ప੉࠶ ߸҃ਸ Ѩࢎೣ Room ীࢲ ࢎਊߑߨ LiveData RxJava2 Flowable/Publisher DAOীࢲ ਤ ೦ݾਸ ࢎਊ

Slide 63

Slide 63 text

Invalidation Tracker We create an in memory table with (version, table_id) where version is an auto-increment primary key and a table_id (hardcoded int from initialization). ObservedTableTracker tracks list of tables we should be watching (e.g. adding triggers for). Before each beginTransaction, RoomDatabase invokes InvalidationTracker to sync trigger states. After each endTransaction, RoomDatabase invokes InvalidationTracker to refresh invalidated tables. Each update on one of the observed tables triggers an insertion into this table, hence a new version. Unfortunately, we cannot override the previous row because sqlite uses the conflict resolution of the outer query (the thing that triggered us) so we do a cleanup as we sync instead of letting SQLite override the rows. https://sqlite.org/lang_createtrigger.html: An ON CONFLICT clause may be specified as part of an UPDATE or INSERT action within the body of the trigger. However if an ON CONFLICT clause is specified as part of the statement causing the trigger to fire, then conflict handling policy of the outer statement is used instead.

Slide 64

Slide 64 text

Database migration Migration ௿ېझ ੉ਊ startVersion, endVersion ૑੿ ୭न ߡ੹ਵ۽ ੉੹ೞӝী ୽࠙ೠ ݃੉Ӓۨ੉࣌ ઁҕೞ૑ ঋח ҃ ਋ ؘ੉ఠ߬੉झܳ ੤੘ࢿೞ޲۽ ݽٚ ؘ੉ఠ ࣚप

Slide 65

Slide 65 text

https://developer.android.com/topic/libraries/architecture/room.html Room.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
 .addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();
 
 static final Migration MIGRATION_1_2 = new Migration(1, 2) {
 @Override
 public void migrate(SupportSQLiteDatabase database) {
 database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, "
 + "`name` TEXT, PRIMARY KEY(`id`))");
 }
 };
 static final Migration MIGRATION_2_3 = new Migration(2, 3) {
 @Override
 public void migrate(SupportSQLiteDatabase database) {
 database.execSQL("ALTER TABLE Book " + " ADD COLUMN pub_year INTEGER");
 }
 };

Slide 66

Slide 66 text

Migration ...

Slide 67

Slide 67 text

Migration ...

Slide 68

Slide 68 text

Testing migrations పझ౟оמೠ ݃੉Ӓۨ੉࣌ ӝמ ઁҕ

Slide 69

Slide 69 text

https://developer.android.com/topic/libraries/architecture/room.html#db-migration // build.gradle
 android {
 ...
 defaultConfig {
 ...
 javaCompileOptions {
 annotationProcessorOptions {
 arguments = ["room.schemaLocation":
 "$projectDir/schemas".toString()]
 }
 }
 }
 ...
 } Testing migrations (1) ݢ੷ ؘ੉ఠ߬੉झ झః݃ܳ ղࠁղঠ೤פ׮. Room਷ ஹ౵ੌद ؘ੉ఠ߬੉झ੄ झః݃ ੿ࠁ ܳ JSON ౵ੌਸ ࢤࢿೞ޲۽, build.gradle ౵ ੌীࢲ room.schemaLocation Annotation ೐۽ࣁࢲ ࣘࢿਸ ࢸ੿ೠ׮.

Slide 70

Slide 70 text

https://developer.android.com/topic/libraries/architecture/room.html#db-migration // build.gradle
 android { ...
 sourceSets {
 androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
 }
 ...
 dependencies {
 androidTestCompile "android.arch.persistence.room:testing"
 }
 } Testing migrations (2) ‘android.arch.persistence.ro om:testing’ ਸ ઙࣘࢿী ୶оೞ Ҋ, ղࠁմ झః݃ ౵ੌ (JSON) ਸ asset ಫ؊ী ߓ஖ೠ׮.

Slide 71

Slide 71 text

https://developer.android.com/topic/libraries/architecture/room.html#db-migration @RunWith(AndroidJUnit4.class)
 public class MigrationTest {
 private static final String TEST_DB = "migration-test";
 
 @Rule
 public MigrationTestHelper helper;
 
 public MigrationTest() {
 helper = new MigrationTestHelper(InstrumentationRegistry.getInstrumentation(),
 MigrationDb.class.getCanonicalName(),
 new FrameworkSQLiteOpenHelperFactory());
 }
 …
 } Testing migrations (3) MigrationTestHelper ௿ېझܳ ੉ਊ೧ࢲ झః݃ ౵ੌਸ ੍যٜੋ׮.

Slide 72

Slide 72 text

https://developer.android.com/topic/libraries/architecture/room.html#db-migration @RunWith(AndroidJUnit4.class)
 public class MigrationTest {
 @Test
 public void migrate1To2() throws IOException {
 // DB۽ ૑੿ೞח Schema Versionਵ۽ ੘ࢿ
 SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, 1);
 
 // Daoח ୭न Schemaী ੄ઓೞ޲۽ ࢎਊ ࠛоמ
 // Ӓېࢲ ࣻ੘সਵ۽ ؘ੉ఠܳ ֍যঠೠ׮.
 db.execSQL(...);
 
 // Migrationী ؀࠺ೞৈ dbܳ ײח׮
 db.close();
 ... Testing migrations (4)

Slide 73

Slide 73 text

https://developer.android.com/topic/libraries/architecture/room.html#db-migration ...
 // ਗೞח ߡ੹ী ؀ೠ ݃੉Ӓۨ੉࣌ ೐۽ࣁझܳ ઁҕ
 db = helper.runMigrationsAndValidate(TEST_DB, 2, true, MIGRATION_1_2);
 
 // MigrationTestHelperо झః݃ ߸҃ ࢎ೦ਸ ੗زਵ۽ ഛੋ
 // ؘ੉ఠо ৢ߄ܰѱ ੉੹غ঻ח૑ ഛੋ೧ળ׮ // SELECT ޙ ١ਸ ੉ਊ೧ࢲ ೠߣ ؊ Ѩૐೞח Ѫਸ ୶ୌ
 }
 } Testing migrations (5)

Slide 74

Slide 74 text

https://developer.android.com/topic/libraries/architecture/room.html Entites DAO Primary key @Insert, @Update, @Delete Passing a collection of arguments Querying multiple tables Indices and uniqueness @Query Observable queries type converters Relationships Passing parameters into the query RxJava Nested objects Returning subsets of columns Direct cursor access

Slide 75

Slide 75 text

Database ܳ ੉ਊೞ۰ח ӝמ ݽ਺ पઁ DBী ੷੢غח ؘ੉ఠ Entity৬ Dao੄ ূ౟ܻ ನੋ౟ @Entity @Dao @Database

Slide 76

Slide 76 text

୭ઙ ੿ܻ

Slide 77

Slide 77 text

ۄ੉೐ࢎ੉௿җ ੜ োزغח Android জ ࢸ҅ী ب਑غח ૑ஜ

Slide 78

Slide 78 text

ޥо ࠗ઒ೠоਃ? android-architecture-components/BasicRxJavaSample Lifecycle / LiveData / ViewModel Room / Room RxJava RxJava2

Slide 79

Slide 79 text

ޥо ࠗ઒ೠоਃ? (2) android-architecture-components/GithubBrowserSample Lifecycle / LiveData / ViewModel Room Dagger2 Fragment р੄ ؘ੉ఠ ҕਬ

Slide 80

Slide 80 text

ޥо ࠗ઒ೠоਃ? (3) android-architecture-components/PersistenceMigrationsSample Room Migration

Slide 81

Slide 81 text

ଵҊ উ٘۽੉٘ ইఃఫ୊ о੉٘৬ ইఃఫ୊ ஹಌք౟ী ؀೧ ഛੋ೧ ࠁࣁਃ. Android Architecture Components Introduction to Android Architecture Components Android Architecture Components android-architecture-components΀κϸϜϰΧϜϯ΀᤼ᅻ΀ॲሑ΀ᇥΞΤ฼͸ΑΝ [Android Architecture Components] Lifecycle, LiveData and ViewModel ᓮḑ [Android Architecture Components] - Room ᓮḑ

Slide 82

Slide 82 text

Thank you, reviewer - ӣకഐ (ҳӖ ௏ܻই) - ੿थ਌ (Android GDE) - ӂకജ (ঌ૑ೖ௏ܻই) - ੉थ޹ (٘ۄ݃ঙஹಌפ)