Realm实战总结--平台搭建

近期在项目中使用了Realm数据库,在此记录一下基本的配置和使用过程。后面再写一篇在使用过程中自己遇到的坑和用chrome如果浏览其中的数据库内容。
Realm 是一个跨平台的移动数据库引擎,它是专门为移动应用所设计的数据持久化解决方案。当然,其它还有像GreenDao、ORMLite等等。

配置

下面以IDE工具AndroidStudio为例。如果你的AS版本是>=1.5版本,则按下面的配置来。在工程app目录下的build.gradle文件配置以下内容即可引入realm:

	buildscript {
		repositories {
			jcenter()
		}
	
	    dependencies {
	        classpath 'com.android.tools.build:gradle:2.1.0'
	        classpath "io.realm:realm-gradle-plugin:1.1.1"
	    }
	}
	
	//android studio版本>=1.5.1
	apply plugin: 'realm-android'

如果你的AS版本低于1.5,则按下面的配置即可:

	buildscript {
	    repositories {
	        maven {
	            jcenter()
	        }
	    }
	
	    dependencies {
	        classpath 'com.android.tools.build:gradle:2.1.0'
	    }
	}
	
	dependencies {
		//android studio版本<1.5.1
		compile 'io.realm:realm-android:0.87.5'
	}

添加Realm数据库会造成apk包增加4M左右,因为引入了不少so库;但是每个平台,其实只需要一种so库就可以了,所以我们可以通过在build.gradle 的 android 里的 defaultConfig 内添加如下内容,引入平台相关的so库:

defaultConfig {  
    ndk {  
        abiFilters "armeabi", "armeabi-v7a", "x86"  
    }  
}  

具体可以参考:android so 库兼容性

Realm基础知识

Realm提供了一个默认的数据文件配置,如果使用默认的,可以使用以下命令进行初始化:

	RealmConfiguration config = new RealmConfiguration.Builder(context).build();
	Realm.setDefaultConfiguration(config);//设置数据库默认配置文件
	Realm realm = Realm.getDefaultInstance();//使用默认数据库

这样,在应用的data/data/com.xxx.xxx/files目录下就会有一个叫default.realm的文件,用于存放你的数据信息;还有一个叫default.realm.lock的文件,它是用来锁定数据库的,防止在你使用数据库过程中,数据库又被其它应用修改。

还可以通过RealmConfiguration自定义Realm数据库的名字:

	RealmConfiguration config = new RealmConfiguration.Builder(con)
                .schemaVersion(0)//数据库版本
                .migration(migration)//升降级处理
                .modules(new AppModule())//此库可以存储的类
               	.name("test.realm")//数据库名字
                .build();
	Realm realm = Realm.getInstance(config);//即可找到相应配置的数据库文件

先介绍一下modules配置。Realm会将系统所有继承自RealmObject的类存到同一个schema中,如果你想限制一个realm数据库只能存储指定的JavaBean,则需要配置modules。具体如下:

首先通过Realm提供的注解方法创建一个RealmModule,Realm针对application和library提供区分,它们的注解稍微有一点点不同:

app注解:

	@RealmModule (classes = {JavaBean1.class, JavaBean2.class})
	public class AppModule {
	}

library注解,多了个library=true的标注:

	@RealmModule (library = true, classes = {JavaBean3.class})
	public class LibraryModule {
	}

这样,就可以在创建RealmConfiguration文件的时候直接new AppModule()。

再介绍一下migration配置。这个是Realm数据库做迁移用的,即我们平时所说的数据库升降级处理,android sqlite的onUpgrade、onDowngrade。

	//升级降级数据库
	 protected RealmMigration migration = new RealmMigration() {
        @Override
        public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {

            // DynamicRealm exposes an editable schema
            RealmSchema schema = realm.getSchema();

            if (oldVersion > newVersion) {//数据库降级
                if (mConfigsList != null && mConfigsList.size() > 0) {
                    for (RealmConfiguration config : mConfigsList) {
                        Realm.deleteRealm(config);
                    }
                }
            } else if (oldVersion < newVersion) {//数据库升级

            }
        }
    };

Realm实例

首先创建一个java类,继承自RealmObject,有一点规定就是所有要存储到数据库的字段都必须是private的,并且必须要有一个public的还带参数的空构造方法,默认此方法可以不写。

	public class UserInfo extends RealmObject {
	    @PrimaryKey
	    private String userId;//主键
	    private String userName;
	    
		public UserInfo(){
		}

		public void setUserId(String userId){
			this.userId = userId;
		}

		public String getUserId(){
			return userId;
		}

		public void setUserName(String userName){
			this.userName = userName;
		}

		public String getUserName(){
			return userName;
		}
	}

创建一个操作此模型的帮助类:

	public class UserInfoDbHelper {

	    private static volatile UserInfoDbHelper mInstance;
	
	    private UserInfoDbHelper(){
	        super();
	        mDefaultConfig = new RealmConfiguration.Builder(MzAccountManager.getInstance().getContext())
	                .schemaVersion(0)
	                .migration(migration)
	                .modules(new AppModule())//只存app的module
	                .name("user.realm")
	                .build();
	    }
	
	    public static UserInfoDbHelper getInstance(){
	        if(mInstance == null){
	            synchronized (UserInfoDbHelper.class){
	                if(mInstance == null){
	                    mInstance = new UserInfoDbHelper();
	                }
	            }
	        }
	        return mInstance;
	    }
	
	    private Realm createRealm() {
	        return createRealmByConfig(mDefaultConfig);
	    }
	
	    private Realm createRealmByConfig(RealmConfiguration config){
	        mConfigsList.add(config);
	        return Realm.getInstance(config);
	    }
	
	    /**
	     * 添加用户基本信息
	     * @param info
	     */
	    public void insertUserInfo(UserInfo info){
	        Realm realm = createRealm();
	        realm.beginTransaction();
	        realm.copyToRealmOrUpdate(info);
	        realm.commitTransaction();
	        realm.close();
	    }
	
	    /**
	     * 查询指定用户
	     * @param userId
	     * @return
	     */
	    @Nullable
	    public UserInfo queryUserInfo(String userId){
	        Realm realm = createRealm();
	        UserInfo info = realm.where(UserInfo.class).equalTo("userId", userId).findFirst();
	        UserInfo result = null;
	        if(info != null) {
	            result = realm.copyFromRealm(info);
	        }
	        realm.close();
	        return result;
	    }
	
	    /**
	     * 查询全部用户
	     * @return
	     */
	    public List<UserInfo> queryUserInfos(){
	        Realm realm = createRealm();
	        RealmResults<UserInfo> realmResults = realm.where(UserInfo.class).findAll();
	        List<UserInfo> arrayList = realm.copyFromRealm(realmResults);
	        realm.close();
	        return arrayList;
	    }
	
	    /**
	     * 删除指定用户
	     * @param userId
	     */
	    public void deleteUserInfo(String userId){
	        Realm realm = createRealm();
	        UserInfo info = realm.where(UserInfo.class).equalTo("userId", userId).findFirst();
	        if(info != null) {
	            realm.beginTransaction();
	            info.deleteFromRealm();
	            realm.commitTransaction();
	        }
	        realm.close();
	    }
	
	    /**
	     * 删除全部用户信息
	     */
	    public void deleteAllUserInfo(){
	        Realm realm = createRealm();
	        realm.beginTransaction();
	        realm.delete(UserInfo.class);
	        realm.commitTransaction();
	        realm.close();
	    }
	}

需要注意的是一个Realm只能在同一个线程中访问,在子线程中进行数据库操作必须重新获取Realm对象,即Realm实例、RealmObject、RealmQuery以及RealmResults不可以跨线程使用。如果Realm关闭,所有查询得到的RealmObject都不能使用了。像上面的Helper类,查询出来的数据,我使用了copyFromRealm方法,将它们重新赋值给新的对象再返回给外部使用。

Realm现在还不支持多进程访问。不同进程请使用不同的 Realm 文件拷贝。后续会支持。 详见:https://realm.io/docs/java/latest/#section-32

Realm转成Android Provider形式

Realm现在还不支持Android Provider形式,但如果实在有必要转成Provider供其它应用共享数据,可以采取类似下面的方式:

	String[] mColumns = new String[] {"userId", "userName"};

	//查询
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
	String[] selectionArgs, String sortOrder) {
		Realm realm = Realm.getInstance(config);
		RealmQuery<UserInfo> query = realm.where(UserInfo.class);
		RealmResults<UserInfo> results = query.findAll();
		MatrixCursor matrixCursor = new MatrixCursor(mColumns);
		for (UserInfo info : results) {
			Object[] rowData = new Object[]{info.getUserId(), info.getUserName()};
			matrixCursor.addRow(rowData);
		}
		return matrixCursor;
	}

	//插入
	@Override
	public Uri insert(Uri uri, ContentValues contentValues) {
		Realm realm = Realm.getInstance(config);
		realm.beginTransaction();
		UserInfo info = realm.createObject(UserInfo.class);
		String userId = contentValues.getAsString(mColumns[0]);
		item.setUserId(userId);
		item.setUserName(contentValues.getAsString(mColumns[1]));
		realm.commitTransaction();
		realm.close();
		return Uri.withAppendedPath(uri, String.valueOf(userId));
	}

有关Realm的操作还有很多,比如异步查询、异步事物、加密、适配器等;还有其它语言的,如Swift、Object-C等,详情可以参考官方文档:

Englist

中文

在RecyclerView中使用Realm

顺带记录一个不错的RecyclerView项目:UltimateRecyclerView

感兴趣的同鞋还可以看Realm相关的文章:

文章目录
  1. 1. 配置
  2. 2. Realm基础知识
  3. 3. Realm实例
  4. 4. Realm转成Android Provider形式
|