본문 바로가기
개발일기/스타일판다

realm 적용하기

by 유주원 2016. 8. 7.

이 번 프로젝트부터 splite 대신 realm을 적용해 보기로 했다.


적용해서 사용해본 결과 너무 편함!! 일단 코드가 너무 간결해 졌다.


우선 realm을 적용하기 위해서는 아래와 같이 gradle 설정이 필요하다. 프로젝트의 gradle 파일에 아래의 정보를 추가한다.


buildscript {

    repositories {

        jcenter()

    }

    dependencies {

        classpath 'io.realm:realm-gradle-plugin:1.1.1'

    }

}


app의 gradle 파일을 수정한다.


apply plugin: 'realm-android'


...

dependencies {

    ....

    compile 'io.realm:android-adapters:1.3.0'

    ....

}


proguard는 따로 설정할 필요가 없다.


위와 같이 설정하면 realm을 사용하기 위한 기본 설정은 끝이 났다.


그럼 이제 실제로 사용해보자.


realm을 사용하기 위해서는 DB 테이블에 해당하는 모델이 있어야 한다.


import io.realm.RealmObject;

import io.realm.annotations.PrimaryKey;


public class VersionDB extends RealmObject {

@PrimaryKey

private long id;

private int version;


public long getId() { return id; }

public void setId(long id) { this.id = id; }


public int getVersion() { return version; }

public void setVersion(int version) { this.version = version; }

}




참고로 realm에서는 auto increment 기능이 따로 없는 것 같다. 

따로 auto increment를 적용하기 위해서는 가장 큰 id 값을 가져온 다음에 1씩 늘려 주는 방식으로 구현해야 할 것이다.


그럼 이제 만들어진 모델을 실제로 사용해보자.


private Realm realm;


private void CheckDB(){

RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this).build();

realm = Realm.getInstance(realmConfiguration);

VersionDB version = realm.where(VersionDB.class).findFirst();


if(version == null){

realm.executeTransaction(new Realm.Transaction(){

@Override

public void execute(Realm realm){

VersionDB version = realm.createObject(VersionDB.class);

version.setId(0);

version.setVersion(1);

}

});

}

}


realmConfiguration은 realm이 파일로 저장된 위치의 구성 정보를 가져와서 instance를 만들 수 있는 역할을 해준다.

만들어진 instance를 가지고 이제 메모리 상에서 read, write를 하는 것이다. 

ORM과 비슷하게 where 함수를 이용해서 정보를 찾고 transaction으로 묶을 수도 있다.


아마 위의 코드를 sqlite로 짰다면 sql문도 들어갔을테고, while문을 돌며 cursor를 하나씩 옮기는 작업도 들어 갔을 것이다.

즉, realm이 훨씬 간결하고 쉽다는 것이다.


realm의 사용이 다 끝났다면  realm.close()를 반드시 해줘야 한다.


realm.close();


주의할 사항이 위와 같이 코드를 작성하고 만약에 모델의 field를 추가한다던지 변경이 일어나면 realm에서는 기존 필드와 다르기 때문에 merging해야 한다고 에러를 내밷을 것이다. 나같은 경우에는 이런 것을 막아주기 위해서 필드를 변경한 다음에는 configuration을 만든 이 후 코드에 아래의 코드를 추가했다.


realm.deleteRealm(realmConfiguration); 




이렇게 되면 기존의 저장되었던 realm의 데이터는 전부 삭제되고 새로운 필드로 다시 시작하게 된다.


realm에서의 delete는 약간 좀 헤멨었는데 위와 같이 findFirst() 함수를 써서 가져오는 경우에는 delete가 안되는 것 같다.

아래와 같이 RealmResults 객체를 리턴으로 받는 findAll()을 쓴다음에 지워줘야 하는 것 같았다.


private RealmResults<VersionDB> mVersionDBs;


private void deleteDB(){

mVersionDBs = realm.where(VersionDB.class).equalTo("id", 1).findAll();

realm.executeTransaction(new Realm.Transaction() {

@Override

public void execute(Realm realm){

mVersionDBs.deleteAllFromRealm();

}

});

}


마지막으로 RealmResults로 받은 객체를 ArrayList등으로 변환 하지 않고 그대로 Adapter로 적용할 수가 있다.


public class RealmAdapter extends RealmBaseAdapter<VersionDB> implements ListAdapter{

private OrderedRealmCollection<VersionDB> mData;


public RealmAdapter(Context context, final int resourceId, OrderedRealmCollection<VersionDB> data) {

super(context, mData);

mData = data;

}


@Override

public int getCount() { return mData == null ? 0 : mData.size(); }


@Override

public VersionDB getItem(int position) { return mData.get(position); }


@Override

public long getItemId(int position) { return position; }

}


위와 같은 adapter를 적용해서 사용하면 RealmResults에 대한 객체도 ListView 등에서 사용할 수가 있다.