SlideShare ist ein Scribd-Unternehmen logo
1 von 66
Downloaden Sie, um offline zu lesen
Extended
Seoul
Architecture Components


alpaca@vcnc.co.kr
Speaker
• (@plazgun)

• Between Android Developer
Architecture Components
• Google I/O 2017 

Architecture Components - Introduction

Architecture Components - Solving the Lifecycle

Architecture Components - Persistence and Offline

• 

• https://developer.android.com/topic/libraries/architecture/
index.html
Architecture Components
• Handling Lifecycles

• LiveData

• ViewModel

• Room
build.gradle
• allprojects {

repositories {

jcenter()

maven { url 'https://maven.google.com' }

}

} 

• compile "android.arch.lifecycle:runtime:1.0.0-alpha3"

compile "android.arch.lifecycle:extensions:1.0.0-alpha3"

annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha3"

• compile "android.arch.persistence.room:runtime:1.0.0-alpha3"

annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha3"

• compile "android.arch.persistence.room:rxjava2:1.0.0-alpha3"

testCompile "android.arch.persistence.room:testing:1.0.0-alpha3"
Handling Lifecycles
public class MyActivity extends AppCompatActivity {
private TestListener testListener;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
testListener = new TestListener();
}
@Override
protected void onStart() {
super.onStart();
testListener.start();
}
@Override
protected void onStop() {
super.onStop();
testListener.stop();
}
}
public class MyActivity extends AppCompatActivity {
private TestListener testListener;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
testListener = new TestListener();
}
@Override
protected void onStart() {
super.onStart();
testListener.start();
}
@Override
protected void onStop() {
super.onStop();
testListener.stop();
}
}
onStart 

Override .
Lifecycle .
Handling Lifecycles
• Lifecycle

• LifecycleOwner

• LifecycleObserver
public class MyActivity extends LifecycleActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle);
TestListener testListener = new TestListener(

getLifecycle(), 

result -> {
// update UI
});
}
}
public class TestListener implements LifecycleObserver {
private Lifecycle lifecycle;
public TestListener(Lifecycle lifecycle, TestCallback callback) {
lifecycle.addObserver(this);
this.lifecycle = lifecycle;
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void start() {
// start Event
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
void clean() {
lifecycle.removeObserver(this);
}
}
public class MyActivity extends CustomActivity {
@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}
}
public class LifecycleActivity extends FragmentActivity 

implements LifecycleRegistryOwner {
private final LifecycleRegistry mRegistry 

= new LifecycleRegistry(this);
@Override
public LifecycleRegistry getLifecycle() {
return mRegistry;
}
}
public class MyActivity extends CustomActivity implements LifecycleRegistryOwner {
private final LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
@Override
public LifecycleRegistry getLifecycle() {
return lifecycleRegistry;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle);
TestListener testListener = new TestListener(getLifecycle(), state -> {
// update Ui
});
}
}
public class MyActivity extends LifecycleActivity {
private TestListener testListener;
@Override
protected void onStart() {
super.onStart();
Utils.checkUserStatus(state -> {
if (state.equals("OK")) {
testListener.start();
}
});
}
public class MyActivity extends LifecycleActivity {
private TestListener testListener;
@Override
protected void onStart() {
super.onStart();
// ?
Utils.checkUserStatus(state -> {
if (state.equals("OK")) {
testListener.start();
}
});
}
StartCreate Resume Pause Stop Destroy
testListener.stop
Utils.checkStatus testListener.start
Activity .
public class MyActivity extends LifecycleActivity {
private TestListener testListener;
@Override
protected void onStart() {
super.onStart();
Utils.checkUserStatus(state -> {
if (state.equals("OK") && getLifecycle()

.getCurrentState()

.isAtLeast(Lifecycle.State.STARTED)) {
testListener.start();
}
});
}
LiveData
LiveData
• Observable Data Holder

• Lifecycle aware

• Automatic subscription management
LiveData<String> stateData = new MutableLiveData<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
stateData.observe((LifecycleOwner) this, ((String) result) -> {
// stateData .
});
}
@Override
protected void onStart() {
super.onStart();
stateData.setValue(“Start");
}
public class StateChangeLiveData extends MutableLiveData<String> {
@Override
protected void onActive() {
super.onActive();

// Active Observer 

// Active: Lifecycle.State STARTED RESUMED
}
@Override
protected void onInactive() {
super.onInactive();

// Active Observer
}
}
ViewModel
public class MyActivity extends LifecycleActivity {
LiveData<User> userData;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
userData = userRepository.fetchData();
userData.observe(this, user -> {
// update UI
});
}
}
StartCreate Resume Pause Stop Destroy
Rotated
fetchData
StartCreate Resume
fetchData
Activity 

.
ViewModel
The ViewModel class is designed to store
and manage UI-related data so that the
data survives configuration changes such
as screen rotations.
”
“
public class UserViewModel extends ViewModel {
}



public class UserViewModel extends AndroidViewModel {

// Application ViewModel

}
ViewModel
• 

• ActivityContext 

• Resource
public class MyActivity extends LifecycleActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.insert_activity);


// ViewModelStore ViewModel .
UserListViewModel viewModel = ViewModelProviders.of(this)

.get(UserListViewModel.class);
public class MyActivity extends LifecycleActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewModelProviders.of(this).get(UserListViewModel.class)
.getData()
.observe(this, user -> {
//update UI
});
public class UserListViewModel extends ViewModel {

private LiveData<User> userLiveData;



public LiveData<User> getData() {

if (userLiveData == null) {

userLiveData = userRepository.fetchData();

}

return userLiveData;

}

}
StartCreate Resume Pause Stop Destroy
Rotated
fetchData
StartCreate Resume
fetchData
StartCreate Resume Pause Stop Destroy
Rotated
StartCreate Resume
ViewModel
fetchData
getData getData
Room
Room
• Sqlite ORM

• Entity

• Dao

• Database
id name create_time
@Entity
public class User {
@PrimaryKey(autoGenerate = true)
private Long id;
String name;
@ColumnInfo(name = "created_time")
private long createdTime;
@Ignore
Bitmap profile;
}
Entity
DAO
@Dao
public interface UserDao {
@Query("SELECT * FROM user")
List<User> getAll();
@Query("SELECT * FROM user WHERE id IN (:userIds)")
List<User> loadAllByIds(int[] userIds);
@Query("SELECT * FROM user WHERE name LIKE :first LIMIT 1")
User findByName(String first);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(User... users);
@Delete
void delete(User user);
@Update
void updateUser(User user);
DAO (Rx, LiveData)
@Query("SELECT * FROM user")
LiveData<List<User>> getAllSync();
@Query("SELECT * FROM user WHERE id = :userId")
LiveData<User> fetchUser(String userId);
@Query("SELECT * from user where id = :id LIMIT 1")
Flowable<User> loadUserByIdRx(int id);
@Query("SELECT * FROM user WHERE age > :minAge LIMIT 5")
Cursor loadRawUsersOlderThan(int minAge);
Database
@Database(entities = {User.class, Book.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {


public abstract UserDao userDao();
public abstract BookDao bookDao();
}
Entity - Embedded
id name created_time image_id image_width image_height
public class Image {
String id;
Integer width;
Integer height;
}
@Entity
public class User {

@PrimaryKey(autoGenerate = true)
private Long id;
String name;


@Embedded(prefix = "image_")
private Image image;
@ColumnInfo(name = "created_time")
private long createdTime;
Entity - TypeConverter
public class User {
@PrimaryKey
private Long id;
@TypeConverters(Converters.class)
private Date date;
public class Converters {
@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();
}
}
Entity - Relation
@Entity(indices = {@Index(value = "id", unique = true)}, 

foreignKeys = {
@ForeignKey(entity = Book.class, 

parentColumns = "id", 

childColumns = "bookId", 

onDelete = ForeignKey.CASCADE)
})
public class User {
@PrimaryKey(autoGenerate = true)
private Long id;
public Long bookId;

}
public class UserDao_Impl implements UserDao {
private final RoomDatabase __db;
private final EntityInsertionAdapter __insertionAdapterOfUser;
private final EntityDeletionOrUpdateAdapter __deletionAdapterOfUser;
private final EntityDeletionOrUpdateAdapter __updateAdapterOfUser;
public UserDao_Impl(RoomDatabase __db) {
this.__db = __db;
this.__insertionAdapterOfUser = new EntityInsertionAdapter<User>(__db) {
@Override
public String createQuery() {
return "INSERT OR REPLACE INTO
`User`(`id`,`name`,`created_time`,`updated_time`,`age`,`bookId`,`image_id`,`image_width`,`image_height`) VALUES
(?,?,?,?,?,?,?,?,?)";
}
@Override
public void bind(SupportSQLiteStatement stmt, User value) {
if (value.getId() == null) {
stmt.bindNull(1);
} else {
stmt.bindLong(1, value.getId());
}
if (value.getName() == null) {
stmt.bindNull(2);
} else {
stmt.bindString(2, value.getName());
}
stmt.bindLong(3, value.getCreatedTime());
if (value.getUpdatedTime() == null) {
stmt.bindNull(4);
} else {
stmt.bindLong(4, value.getUpdatedTime());
}
Error
@Query("SELECT * FROM users”)

List<User> getAll();
Architecture Components
• Handling Lifecycles

• LiveData

• ViewModel

• Room
• RxJava

• greenDAO ( Realm)

• MVP

• Firebase, Retrofit, Dagger, ButterKnife, Fresco, Glide, Mockito …
Android Lifecycle Components 

vs 

ReactiveX
public class TestActivity extends RxFragmentActivity {
@Override
protected void onCreate(@Nullable Bundle b) {
super.onCreate(savedInstanceState);
lifecycle()
.filter(e -> e == ActivityEvent.START)
.subscribe(e -> {
// on start
});
}
}
public class TestActivity extends LifecycleActivity
implements LifecycleObserver {
@Override
protected void onCreate(@Nullable Bundle b) {
super.onCreate(savedInstanceState);
getLifecycle().addObserver(this);
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void start() {
// on start
}
}
LifecycleOwner RxLifecycle
public abstract class RxFragmentActivity
extends FragmentActivity
implements LifecycleProvider<ActivityEvent> {
private final BehaviorSubject<ActivityEvent> lifecycleSubject
= BehaviorSubject.create();
@Override
@NonNull
@CheckResult
public final Observable<ActivityEvent> lifecycle() {
return lifecycleSubject.asObservable();
}
@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleSubject.onNext(ActivityEvent.CREATE);
}
@Override
@CallSuper
protected void onStart() {
super.onStart();
lifecycleSubject.onNext(ActivityEvent.START);
}
}
public class LifecycleActivity extends FragmentActivity
implements LifecycleRegistryOwner {
private final LifecycleRegistry mRegistry
= new LifecycleRegistry(this);
@Override
public LifecycleRegistry getLifecycle() {
return mRegistry;
}
}
LifecycleActivity RxFragmentActivity
public class TestActivity extends RxFragmentActivity {
@Override
protected void onCreate(@Nullable Bundle b) {
super.onCreate(savedInstanceState);
Flowable<Long> data = getData();
data.compose(RxLifecycle.bindUntilEvent(
lifecycle(), ActivityEvent.DESTROY))
.subscribe(d -> {
// update ui
});
}
}
public class TestActivity extends LifecycleActivity {
@Override
protected void onCreate(@Nullable Bundle b) {
super.onCreate(savedInstanceState);
LiveData<Long> data = getData();
data.observe(this, result -> {
// update ui
});
}
}
LiveData RxFlowable
Don’t migrate from RxJava
But be sure that you correctly handle lifecycle.

”
“
Room vs greenDAO vs Realm
@Entity
public class RoomUser {
@PrimaryKey
private long id;
// getter & setter
}
Room
greenDAO
Realm
@Entity
public class GreenUser {
@Id
private long id;
// getter & setter
}
public class RealmUser extends RealmObject {
@PrimaryKey
private long id;
// getter & setter
}
@Entity(tableName = "user")
public class RoomUser {
@ColumnInfo(name = “first_name")
private String firstName;
}
@Entity(nameInDb = "user")
public class GreenUser {
@Property(nameInDb = “first_name")
private String firstName;
}
Room
greenDAO
Realm
@Entity(indices = @Index(“address"))
public class RoomUser {
private String address;
@Ignore
private String sessionId;
}
@Entity(indexes = @Index("address DESC"))
public class GreenUser {
private String address;
@Transient
private String sessionId;
}
public class RealmUser extends RealmObject {
@Index
private String address;
@Ignore
private String sessionId;
}
Room
greenDAO
Realm
@Dao
public interface RoomUserDao {
@Query("SELECT * FROM RoomUser WHERE id > 10 ORDER BY id DESC”)
List<RoomUser> getUsers();
}
public class GreenUseCase {
public List<GreenUser> getUsers() {
// get DaoSession
return new daoSession.getGreenUserDao().queryBuilder()
.where(GreenUserDao.Properties.Id.gt(10))
.orderDesc(GreenUserDao.Properties.Id)
.list();
}
}
public class RealmUseCase {
public RealmResults<RealmUser> getUsers() {
// get realm instance
return realm.where(RealmUser.class)
.greaterThan("id", 10)
.findAllSorted("id", Sort.DESCENDING);
}
}
Room
greenDAO
Realm
public class AndroidUser {

private String userId;



private String groupID;

}
public class AndroidGroup {



private String groupId;



private String groupName;



private List<AndroidUser> roomUser;

}
Relation
@Entity
public class RoomGroup {
@PrimaryKey
private long id;
}
@Entity(foreignKeys = @ForeignKey(
entity = RoomGroup.class,
parentColumns = "id",
childColumns = "groupId"))
public class RoomUser {
@PrimaryKey
private long id;
private long groupId;
}
https://developer.android.com/topic/libraries/architecture/room.html#no-object-references
Relation - Room
@Dao
public interface RoomGroupDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertGroup(RoomGroup group);
@Query("SELECT * FROM RoomGroup WHERE id = :id")
LiveData<RoomGroup> getGroup(long id);
}
@Dao
public interface RoomUserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertUsers(List<RoomUser> users);
@Query("SELECT * FROM RoomUser WHERE groupId = :groupId")
LiveData<List<RoomUser>> getUsers(long groupId);
}
@Entity
public class GreenGroup {
@Id
private long id;
@ToMany(referencedJoinProperty
= "groupId")
private List<GreenUser> users;
}
@Entity
public class GreenUser {
@Id
private long id;
private long groupId;
}
Relation - greenDAO
public class GreenUseCase {
public void insertGroup(GreenGroup group) {
daoSession.getGreenGroupDao()
.insertOrReplace(group);
daoSession.getGreenUserDao()
.insertOrReplaceInTx(group.getUsers());
}
public GreenGroup getGroup(long groupId) {
return daoSession.getGreenGroupDao()
.queryBuilder()
.where(GreenGroupDao.Properties.Id.eq(groupId))
.build()
.unique();
}
}
public class RealmGroup extends RealmObject {
@PrimaryKey
private long id;
RealmList<RealmUser> users;
}
public class RealmUser extends RealmObject {
@PrimaryKey
private long id;
}
Relation - Realm
public class RealmUseCase {
public void insertGroup(RealmGroup group) {
realm.insertOrUpdate(group);
}
public RealmGroup getGroup(long groupId) {
return realm.where(RealmGroup.class)
.equalTo("id", groupId)
.findFirst();
}
}
Realm GreenDao Room
Core Native Library SQLite SQLite
Performance Realm Realm
Relation


.
QueryBuilder X
DeepInsert X X
LazyLoading X
Integration Rx Rx, LiveData, Cursor
https://youtu.be/FrteWKKVyzI
https://youtu.be/bEKNi1JOrNs
https://youtu.be/MfHsPGQ6bgE
https://developer.android.com/topic/libraries/architecture/index.html
alpaca@vcnc.co.kr
• http://engineering.vcnc.co.kr/jobs/

Weitere ähnliche Inhalte

Was ist angesagt?

Testdrevet javautvikling på objektorienterte skinner
Testdrevet javautvikling på objektorienterte skinnerTestdrevet javautvikling på objektorienterte skinner
Testdrevet javautvikling på objektorienterte skinner
Truls Jørgensen
 
Automated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.xAutomated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.x
Tatsuya Maki
 
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Ryosuke Uchitate
 

Was ist angesagt? (20)

What's in the Latest Java
What's in the Latest JavaWhat's in the Latest Java
What's in the Latest Java
 
Android Architecture Components
Android Architecture ComponentsAndroid Architecture Components
Android Architecture Components
 
Testdrevet javautvikling på objektorienterte skinner
Testdrevet javautvikling på objektorienterte skinnerTestdrevet javautvikling på objektorienterte skinner
Testdrevet javautvikling på objektorienterte skinner
 
Тарас Олексин - Sculpt! Your! Tests!
Тарас Олексин  - Sculpt! Your! Tests!Тарас Олексин  - Sculpt! Your! Tests!
Тарас Олексин - Sculpt! Your! Tests!
 
Backbone.js
Backbone.jsBackbone.js
Backbone.js
 
CDI 2.0 Deep Dive
CDI 2.0 Deep DiveCDI 2.0 Deep Dive
CDI 2.0 Deep Dive
 
Android Architecture - Khoa Tran
Android Architecture -  Khoa TranAndroid Architecture -  Khoa Tran
Android Architecture - Khoa Tran
 
Automated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.xAutomated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.x
 
Spock
SpockSpock
Spock
 
Advanced Akka For Architects
Advanced Akka For ArchitectsAdvanced Akka For Architects
Advanced Akka For Architects
 
SolrJ: Power and Pitfalls - Jason Gerlowski, Lucidworks
SolrJ: Power and Pitfalls - Jason Gerlowski, LucidworksSolrJ: Power and Pitfalls - Jason Gerlowski, Lucidworks
SolrJ: Power and Pitfalls - Jason Gerlowski, Lucidworks
 
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
 
SQLite 周りのテストをしよう
SQLite 周りのテストをしようSQLite 周りのテストをしよう
SQLite 周りのテストをしよう
 
Junit 5 - Maior e melhor
Junit 5 - Maior e melhorJunit 5 - Maior e melhor
Junit 5 - Maior e melhor
 
Wicket Security Presentation
Wicket Security PresentationWicket Security Presentation
Wicket Security Presentation
 
Accessibility Testing using Axe
Accessibility Testing using AxeAccessibility Testing using Axe
Accessibility Testing using Axe
 
Test-driven Development with AEM
Test-driven Development with AEMTest-driven Development with AEM
Test-driven Development with AEM
 
Unit Testing at Scale
Unit Testing at ScaleUnit Testing at Scale
Unit Testing at Scale
 
Wicket 6
Wicket 6Wicket 6
Wicket 6
 
yagdao-0.3.1 JPA guide
yagdao-0.3.1 JPA guideyagdao-0.3.1 JPA guide
yagdao-0.3.1 JPA guide
 

Ähnlich wie Architecture Components

Ähnlich wie Architecture Components (20)

Android architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta IndonesiaAndroid architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta Indonesia
 
Architecture components - IT Talk
Architecture components - IT TalkArchitecture components - IT Talk
Architecture components - IT Talk
 
Android Architecture Components - Guy Bar on, Vonage
Android Architecture Components - Guy Bar on, VonageAndroid Architecture Components - Guy Bar on, Vonage
Android Architecture Components - Guy Bar on, Vonage
 
Android Architecture Components with Kotlin
Android Architecture Components with KotlinAndroid Architecture Components with Kotlin
Android Architecture Components with Kotlin
 
Presentation Android Architecture Components
Presentation Android Architecture ComponentsPresentation Android Architecture Components
Presentation Android Architecture Components
 
What's Coming in Spring 3.0
What's Coming in Spring 3.0What's Coming in Spring 3.0
What's Coming in Spring 3.0
 
Teste de Integração com DbUnit e jIntegrity
Teste de Integração com DbUnit e jIntegrityTeste de Integração com DbUnit e jIntegrity
Teste de Integração com DbUnit e jIntegrity
 
Android dev toolbox
Android dev toolboxAndroid dev toolbox
Android dev toolbox
 
A evolução da persistência de dados (com sqlite) no android
A evolução da persistência de dados (com sqlite) no androidA evolução da persistência de dados (com sqlite) no android
A evolução da persistência de dados (com sqlite) no android
 
比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotation
 
Struts2 - 101
Struts2 - 101Struts2 - 101
Struts2 - 101
 
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture Components
 
Testing basics for developers
Testing basics for developersTesting basics for developers
Testing basics for developers
 
Migrating from Struts 1 to Struts 2
Migrating from Struts 1 to Struts 2Migrating from Struts 1 to Struts 2
Migrating from Struts 1 to Struts 2
 
Codemotion appengine
Codemotion appengineCodemotion appengine
Codemotion appengine
 
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディングXitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
 
Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014
 
Annotation processing and code gen
Annotation processing and code genAnnotation processing and code gen
Annotation processing and code gen
 
Mail OnLine Android Application at DroidCon - Turin - Italy
Mail OnLine Android Application at DroidCon - Turin - ItalyMail OnLine Android Application at DroidCon - Turin - Italy
Mail OnLine Android Application at DroidCon - Turin - Italy
 

Kürzlich hochgeladen

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Kürzlich hochgeladen (20)

Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
A Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source MilvusA Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source Milvus
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 

Architecture Components

  • 3. Architecture Components • Google I/O 2017 
 Architecture Components - Introduction
 Architecture Components - Solving the Lifecycle
 Architecture Components - Persistence and Offline • • https://developer.android.com/topic/libraries/architecture/ index.html
  • 4. Architecture Components • Handling Lifecycles • LiveData • ViewModel • Room
  • 5. build.gradle • allprojects {
 repositories {
 jcenter()
 maven { url 'https://maven.google.com' }
 }
 } • compile "android.arch.lifecycle:runtime:1.0.0-alpha3"
 compile "android.arch.lifecycle:extensions:1.0.0-alpha3"
 annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha3"
 • compile "android.arch.persistence.room:runtime:1.0.0-alpha3"
 annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha3"
 • compile "android.arch.persistence.room:rxjava2:1.0.0-alpha3"
 testCompile "android.arch.persistence.room:testing:1.0.0-alpha3"
  • 7. public class MyActivity extends AppCompatActivity { private TestListener testListener; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); testListener = new TestListener(); } @Override protected void onStart() { super.onStart(); testListener.start(); } @Override protected void onStop() { super.onStop(); testListener.stop(); } }
  • 8. public class MyActivity extends AppCompatActivity { private TestListener testListener; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); testListener = new TestListener(); } @Override protected void onStart() { super.onStart(); testListener.start(); } @Override protected void onStop() { super.onStop(); testListener.stop(); } } onStart 
 Override .
  • 10. Handling Lifecycles • Lifecycle • LifecycleOwner • LifecycleObserver
  • 11. public class MyActivity extends LifecycleActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_lifecycle); TestListener testListener = new TestListener(
 getLifecycle(), 
 result -> { // update UI }); } }
  • 12. public class TestListener implements LifecycleObserver { private Lifecycle lifecycle; public TestListener(Lifecycle lifecycle, TestCallback callback) { lifecycle.addObserver(this); this.lifecycle = lifecycle; } @OnLifecycleEvent(Lifecycle.Event.ON_START) void start() { // start Event } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) void clean() { lifecycle.removeObserver(this); } }
  • 13. public class MyActivity extends CustomActivity { @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 } }
  • 14. public class LifecycleActivity extends FragmentActivity 
 implements LifecycleRegistryOwner { private final LifecycleRegistry mRegistry 
 = new LifecycleRegistry(this); @Override public LifecycleRegistry getLifecycle() { return mRegistry; } }
  • 15. public class MyActivity extends CustomActivity implements LifecycleRegistryOwner { private final LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this); @Override public LifecycleRegistry getLifecycle() { return lifecycleRegistry; } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_lifecycle); TestListener testListener = new TestListener(getLifecycle(), state -> { // update Ui }); } }
  • 16.
  • 17. public class MyActivity extends LifecycleActivity { private TestListener testListener; @Override protected void onStart() { super.onStart(); Utils.checkUserStatus(state -> { if (state.equals("OK")) { testListener.start(); } }); }
  • 18. public class MyActivity extends LifecycleActivity { private TestListener testListener; @Override protected void onStart() { super.onStart(); // ? Utils.checkUserStatus(state -> { if (state.equals("OK")) { testListener.start(); } }); }
  • 19. StartCreate Resume Pause Stop Destroy testListener.stop Utils.checkStatus testListener.start
  • 21. public class MyActivity extends LifecycleActivity { private TestListener testListener; @Override protected void onStart() { super.onStart(); Utils.checkUserStatus(state -> { if (state.equals("OK") && getLifecycle()
 .getCurrentState()
 .isAtLeast(Lifecycle.State.STARTED)) { testListener.start(); } }); }
  • 23. LiveData • Observable Data Holder • Lifecycle aware • Automatic subscription management
  • 24. LiveData<String> stateData = new MutableLiveData<>(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); stateData.observe((LifecycleOwner) this, ((String) result) -> { // stateData . }); } @Override protected void onStart() { super.onStart(); stateData.setValue(“Start"); }
  • 25. public class StateChangeLiveData extends MutableLiveData<String> { @Override protected void onActive() { super.onActive();
 // Active Observer 
 // Active: Lifecycle.State STARTED RESUMED } @Override protected void onInactive() { super.onInactive();
 // Active Observer } }
  • 27. public class MyActivity extends LifecycleActivity { LiveData<User> userData; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); userData = userRepository.fetchData(); userData.observe(this, user -> { // update UI }); } }
  • 28. StartCreate Resume Pause Stop Destroy Rotated fetchData StartCreate Resume fetchData
  • 30. ViewModel The ViewModel class is designed to store and manage UI-related data so that the data survives configuration changes such as screen rotations. ” “
  • 31. public class UserViewModel extends ViewModel { }
 
 public class UserViewModel extends AndroidViewModel {
 // Application ViewModel
 }
  • 33. public class MyActivity extends LifecycleActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.insert_activity); 
 // ViewModelStore ViewModel . UserListViewModel viewModel = ViewModelProviders.of(this)
 .get(UserListViewModel.class);
  • 34. public class MyActivity extends LifecycleActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ViewModelProviders.of(this).get(UserListViewModel.class) .getData() .observe(this, user -> { //update UI }); public class UserListViewModel extends ViewModel {
 private LiveData<User> userLiveData;
 
 public LiveData<User> getData() {
 if (userLiveData == null) {
 userLiveData = userRepository.fetchData();
 }
 return userLiveData;
 }
 }
  • 35. StartCreate Resume Pause Stop Destroy Rotated fetchData StartCreate Resume fetchData
  • 36. StartCreate Resume Pause Stop Destroy Rotated StartCreate Resume ViewModel fetchData getData getData
  • 37. Room
  • 38. Room • Sqlite ORM • Entity • Dao • Database
  • 39. id name create_time @Entity public class User { @PrimaryKey(autoGenerate = true) private Long id; String name; @ColumnInfo(name = "created_time") private long createdTime; @Ignore Bitmap profile; } Entity
  • 40. DAO @Dao public interface UserDao { @Query("SELECT * FROM user") List<User> getAll(); @Query("SELECT * FROM user WHERE id IN (:userIds)") List<User> loadAllByIds(int[] userIds); @Query("SELECT * FROM user WHERE name LIKE :first LIMIT 1") User findByName(String first); @Insert(onConflict = OnConflictStrategy.REPLACE) void insertAll(User... users); @Delete void delete(User user); @Update void updateUser(User user);
  • 41. DAO (Rx, LiveData) @Query("SELECT * FROM user") LiveData<List<User>> getAllSync(); @Query("SELECT * FROM user WHERE id = :userId") LiveData<User> fetchUser(String userId); @Query("SELECT * from user where id = :id LIMIT 1") Flowable<User> loadUserByIdRx(int id); @Query("SELECT * FROM user WHERE age > :minAge LIMIT 5") Cursor loadRawUsersOlderThan(int minAge);
  • 42. Database @Database(entities = {User.class, Book.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { 
 public abstract UserDao userDao(); public abstract BookDao bookDao(); }
  • 43. Entity - Embedded id name created_time image_id image_width image_height public class Image { String id; Integer width; Integer height; } @Entity public class User {
 @PrimaryKey(autoGenerate = true) private Long id; String name; 
 @Embedded(prefix = "image_") private Image image; @ColumnInfo(name = "created_time") private long createdTime;
  • 44. Entity - TypeConverter public class User { @PrimaryKey private Long id; @TypeConverters(Converters.class) private Date date; public class Converters { @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(); } }
  • 45. Entity - Relation @Entity(indices = {@Index(value = "id", unique = true)}, 
 foreignKeys = { @ForeignKey(entity = Book.class, 
 parentColumns = "id", 
 childColumns = "bookId", 
 onDelete = ForeignKey.CASCADE) }) public class User { @PrimaryKey(autoGenerate = true) private Long id; public Long bookId;
 }
  • 46. public class UserDao_Impl implements UserDao { private final RoomDatabase __db; private final EntityInsertionAdapter __insertionAdapterOfUser; private final EntityDeletionOrUpdateAdapter __deletionAdapterOfUser; private final EntityDeletionOrUpdateAdapter __updateAdapterOfUser; public UserDao_Impl(RoomDatabase __db) { this.__db = __db; this.__insertionAdapterOfUser = new EntityInsertionAdapter<User>(__db) { @Override public String createQuery() { return "INSERT OR REPLACE INTO `User`(`id`,`name`,`created_time`,`updated_time`,`age`,`bookId`,`image_id`,`image_width`,`image_height`) VALUES (?,?,?,?,?,?,?,?,?)"; } @Override public void bind(SupportSQLiteStatement stmt, User value) { if (value.getId() == null) { stmt.bindNull(1); } else { stmt.bindLong(1, value.getId()); } if (value.getName() == null) { stmt.bindNull(2); } else { stmt.bindString(2, value.getName()); } stmt.bindLong(3, value.getCreatedTime()); if (value.getUpdatedTime() == null) { stmt.bindNull(4); } else { stmt.bindLong(4, value.getUpdatedTime()); }
  • 47. Error @Query("SELECT * FROM users”)
 List<User> getAll();
  • 48. Architecture Components • Handling Lifecycles • LiveData • ViewModel • Room
  • 49. • RxJava • greenDAO ( Realm) • MVP • Firebase, Retrofit, Dagger, ButterKnife, Fresco, Glide, Mockito …
  • 50. Android Lifecycle Components 
 vs 
 ReactiveX
  • 51. public class TestActivity extends RxFragmentActivity { @Override protected void onCreate(@Nullable Bundle b) { super.onCreate(savedInstanceState); lifecycle() .filter(e -> e == ActivityEvent.START) .subscribe(e -> { // on start }); } } public class TestActivity extends LifecycleActivity implements LifecycleObserver { @Override protected void onCreate(@Nullable Bundle b) { super.onCreate(savedInstanceState); getLifecycle().addObserver(this); } @OnLifecycleEvent(Lifecycle.Event.ON_START) void start() { // on start } } LifecycleOwner RxLifecycle
  • 52. public abstract class RxFragmentActivity extends FragmentActivity implements LifecycleProvider<ActivityEvent> { private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create(); @Override @NonNull @CheckResult public final Observable<ActivityEvent> lifecycle() { return lifecycleSubject.asObservable(); } @Override @CallSuper protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); lifecycleSubject.onNext(ActivityEvent.CREATE); } @Override @CallSuper protected void onStart() { super.onStart(); lifecycleSubject.onNext(ActivityEvent.START); } } public class LifecycleActivity extends FragmentActivity implements LifecycleRegistryOwner { private final LifecycleRegistry mRegistry = new LifecycleRegistry(this); @Override public LifecycleRegistry getLifecycle() { return mRegistry; } } LifecycleActivity RxFragmentActivity
  • 53. public class TestActivity extends RxFragmentActivity { @Override protected void onCreate(@Nullable Bundle b) { super.onCreate(savedInstanceState); Flowable<Long> data = getData(); data.compose(RxLifecycle.bindUntilEvent( lifecycle(), ActivityEvent.DESTROY)) .subscribe(d -> { // update ui }); } } public class TestActivity extends LifecycleActivity { @Override protected void onCreate(@Nullable Bundle b) { super.onCreate(savedInstanceState); LiveData<Long> data = getData(); data.observe(this, result -> { // update ui }); } } LiveData RxFlowable
  • 54. Don’t migrate from RxJava But be sure that you correctly handle lifecycle.
 ” “
  • 55. Room vs greenDAO vs Realm
  • 56. @Entity public class RoomUser { @PrimaryKey private long id; // getter & setter } Room greenDAO Realm @Entity public class GreenUser { @Id private long id; // getter & setter } public class RealmUser extends RealmObject { @PrimaryKey private long id; // getter & setter }
  • 57. @Entity(tableName = "user") public class RoomUser { @ColumnInfo(name = “first_name") private String firstName; } @Entity(nameInDb = "user") public class GreenUser { @Property(nameInDb = “first_name") private String firstName; } Room greenDAO Realm
  • 58. @Entity(indices = @Index(“address")) public class RoomUser { private String address; @Ignore private String sessionId; } @Entity(indexes = @Index("address DESC")) public class GreenUser { private String address; @Transient private String sessionId; } public class RealmUser extends RealmObject { @Index private String address; @Ignore private String sessionId; } Room greenDAO Realm
  • 59. @Dao public interface RoomUserDao { @Query("SELECT * FROM RoomUser WHERE id > 10 ORDER BY id DESC”) List<RoomUser> getUsers(); } public class GreenUseCase { public List<GreenUser> getUsers() { // get DaoSession return new daoSession.getGreenUserDao().queryBuilder() .where(GreenUserDao.Properties.Id.gt(10)) .orderDesc(GreenUserDao.Properties.Id) .list(); } } public class RealmUseCase { public RealmResults<RealmUser> getUsers() { // get realm instance return realm.where(RealmUser.class) .greaterThan("id", 10) .findAllSorted("id", Sort.DESCENDING); } } Room greenDAO Realm
  • 60. public class AndroidUser {
 private String userId;
 
 private String groupID;
 } public class AndroidGroup {
 
 private String groupId;
 
 private String groupName;
 
 private List<AndroidUser> roomUser;
 } Relation
  • 61. @Entity public class RoomGroup { @PrimaryKey private long id; } @Entity(foreignKeys = @ForeignKey( entity = RoomGroup.class, parentColumns = "id", childColumns = "groupId")) public class RoomUser { @PrimaryKey private long id; private long groupId; } https://developer.android.com/topic/libraries/architecture/room.html#no-object-references Relation - Room @Dao public interface RoomGroupDao { @Insert(onConflict = OnConflictStrategy.REPLACE) void insertGroup(RoomGroup group); @Query("SELECT * FROM RoomGroup WHERE id = :id") LiveData<RoomGroup> getGroup(long id); } @Dao public interface RoomUserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) void insertUsers(List<RoomUser> users); @Query("SELECT * FROM RoomUser WHERE groupId = :groupId") LiveData<List<RoomUser>> getUsers(long groupId); }
  • 62. @Entity public class GreenGroup { @Id private long id; @ToMany(referencedJoinProperty = "groupId") private List<GreenUser> users; } @Entity public class GreenUser { @Id private long id; private long groupId; } Relation - greenDAO public class GreenUseCase { public void insertGroup(GreenGroup group) { daoSession.getGreenGroupDao() .insertOrReplace(group); daoSession.getGreenUserDao() .insertOrReplaceInTx(group.getUsers()); } public GreenGroup getGroup(long groupId) { return daoSession.getGreenGroupDao() .queryBuilder() .where(GreenGroupDao.Properties.Id.eq(groupId)) .build() .unique(); } }
  • 63. public class RealmGroup extends RealmObject { @PrimaryKey private long id; RealmList<RealmUser> users; } public class RealmUser extends RealmObject { @PrimaryKey private long id; } Relation - Realm public class RealmUseCase { public void insertGroup(RealmGroup group) { realm.insertOrUpdate(group); } public RealmGroup getGroup(long groupId) { return realm.where(RealmGroup.class) .equalTo("id", groupId) .findFirst(); } }
  • 64. Realm GreenDao Room Core Native Library SQLite SQLite Performance Realm Realm Relation 
 . QueryBuilder X DeepInsert X X LazyLoading X Integration Rx Rx, LiveData, Cursor