11. Realm
Realm 데이터 모델
Realm 데이터 모델은 Java Bean 모델을 따름
RealmObject를 상속하고 Realm 주석 프로세서가 프록시 클래스를 생성
public class User extends RealmObject {
@PrimaryKey
private String name;
private int age;
@Ignore
private int sessionId;
기본키
: 필드 타입이 문자열이거나 정수(short, int, long)이어야 함
여러 필드(혼합 키)를 기본 키로 사용할 수는 없음
속성 무시
: 필드가 디스크에 저장되지 않도록 할 수 있음
12. Realm
Realm 데이터 모델
// Standard getters setters generated by your IDE…
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public int getSessionId() { return sessionId; }
public void setSessionId(int dontPersist) { this.sessionId = sessionId; }
}
13. Realm
Realm 데이터 쓰기
모든 쓰기 오퍼레이션(추가, 수정, 삭제)은 반드시 쓰기 트랜잭션 내에서 이
루어져야 함.
// Obtain a Realm instance
Realm realm = Realm.getInstance(this);
realm.beginTransaction();
User user = realm.createObject(User.class);
user.setName(John);
user.setEmail(john@corporation.com);
realm.commitTransaction();
객체 생성
14. Realm
Realm 데이터 쓰기
객체를 커밋하는 대신에 되돌릴려면 쓰기 트랜잭션을 간단하게 취소할 수
있음.
realm.beginTransaction();
User user = realm.createObject(User.class);
// ...
realm.cancelTransaction();
15. Realm
Realm 데이터 쓰기
수동으로 realm.beginTransaction(), realm.commitTransaction(),
realm.cancelTransaction()을 관리하는 대신에 자동으로 begin/commit을
관리하고 에러가 발생했을 때 cancel 하도록 지원
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
User user = realm.createObject(User.class);
user.setName(John);
user.setEmail(john@corporation.com);
}
});
(트랜잭션 블록)
16. Realm
Realm 쿼리
John 혹은 Peter라는 이름을 가진 모든 사용자를 쿼리하기 위해서는
// Build the query looking at all users:
RealmQueryUser query = realm.where(User.class);
// Add query conditions:
query.equalTo(name, John);
query.or().equalTo(name, Peter);
// Execute the query:
RealmResultsUser result1 = query.findAll();
19. Realm
Realm 객체 닫기
Realm을 사용한 후 Realm 객체를 닫는게 중요
Realm 인스턴스는 레퍼런스 카운팅됩니다. 하나의 쓰레드에서
getInstance()를 두 번 호출하면 사용이 끝난 후 close()도 두 번 호출해야
합니다. 어떠한 쓰레드가 실행될지 걱정없이 Runnable 클래스를 구현하면
됩니다. 간단하게 getInstance()로 시작해서 close()로 끝냅니다
20. Realm
Realm 객체 닫기
UI 쓰레드를 대상으로 한다면 onDestroy() 메소드에서 realm.close()을 호
출하고, AsyncTask를 대상으로 하면 아래의 패턴이 좋음.
protected Long doInBackground(Context... contexts) {
Realm realm = null;
try {
realm = Realm.getInstance(contexts[0]);
// ... Use the Realm instance
} finally {
if (realm != null) {
realm.close();
}
}
}
21. Realm
Realm 관계
Realm에서 관계는 대부분 속도 면에서 부담이 없고 관계를 표현하는 내부
구현은 메모리 사용에 상당히 효율적임.
public class Email extends RealmObject {
private String address;
private boolean active;
// ... setters and getters left out
}
public class Contact extends RealmObject {
private String name;
private Email email;
// ... setters and getters left out
}
22. Realm
Realm 관계
N : 1 관계
public class Contact extends RealmObject {
private Email email;
// Other fields…
}
각 contact는 0 혹은 1 개의 email(Email 인스턴스)을 갖습니다.
보통 이러한 구현은 1 : 1 관계가 일반적입니다.
23. Realm
Realm 관계
N : N 관계
public class Contact extends RealmObject {
private RealmListEmail emails;
// Other fields…
}
RealmList는 기본적으로 RealmObject의 컨테이너이고 Java의 List와 유
사합니다. 서로 다른 RealmList 동일한 객체를 두 번(혹은 이상) 사용할 수
있습니다
24. Realm
Realm JSON
JSON JSONObject으로 표현되거나 String InputStream으로 표현된 데이
터를 직접적으로 RealmObject로 추가할 수 있음.
// Insert from a string
realm.beginTransaction();
realm.createObjectFromJson(City.class, { city: Copenhagen, id: 1 });
realm.commitTransaction();
// Insert multiple items using a InputStream
InputStream is = new FileInputStream(new File(path_to_file));
realm.beginTransaction();
try {
realm.createAllFromJson(City.class, is);
realm.commitTransaction();
} catch (IOException e) {
realm.cancelTransaction();
}
25. Realm
Realm Notification
Listener를 추가해서 사용하는 UI 혹은 다른 쓰레드가 Realm이 변경될 때
감지할 수 있음.
realm.addChangeListener(new RealmChangeListener() {
@Override
public void onChange() {
// ... do something with the updates (UI, etc.) ...
}
});
26. Realm
Realm 암호화
Realm 파일은 512-bit 암호화 키를 Realm.getInstance() 호출에 전달하여
암호화된 상태로 저장
byte[] key = new byte[64];
new SecureRandom().nextBytes(key);
Realm realm = Realm.getInstance(this, key);
// ... use the Realm as normal ...
이 기능을 통해 디스크의 모든 데이터를 AES-256 암호화를 사용하여 쉽게
암호화, 복호화할 수 있음.
27. Realm
Realm GSON
Gson gson = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
@Override
public boolean shouldSkipClass(Class? clazz) {
return false;
}
})
.create();
String json = { name : 'John', email : 'john@corporation.com' };
User user = gson.fromJson(json, User.class);
28. Realm
Realm Retrofit
Retrofit은 내부적으로 GSON을 사용하므로 JSON 데이터에서
RealmObject로 역직렬화할 필요성이 있다면 GsonConverter 설정
(앞 슬라이드에서의 Gson 설정 후 아래 설정 내용 추가)
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(https://api.github.com)
.setConverter(new GsonConverter(gson))
.build();
GitHubService service = restAdapter.create(GitHubService.class);
29. Realm
Realm Retrofit
Retrofit은 자동적으로 객체를 Realm에 추가하지 않으며 수동으로
realm.copyToRealm() 메소드를 사용해서 추가해야 함.
GitHubService service = restAdapter.create(GitHubService.class);
ListRepo repos = service.listRepos(octocat);
// Copy elements from Retrofit to Realm to persist them.
realm.beginTransaction();
ListRepo realmRepos = realm.copyToRealm(repos);
realm.commitTransaction();