Realm源码分析之初始化
来源:互联网 发布:access vba编程入门 编辑:程序博客网 时间:2024/05/29 17:31
Realm源码下载
上篇Realm总结是关于Realm的基础使用,可粗略地概括为如下关系图:
在感受了Realm的强大之后,更让人对其背后的实现原理感到好奇,点击下载Realm源码一探究竟吧。
目前Realm java的版本是3.5,如下工程截图,模块简介如下:
- realm-java工程囊括了好几个模块,而编译配置说明是在工程根目录下的README.md
- examples模块是realm提供的使用demo
- gradle-plugin模块是realm编译使用的插件
- realm模块则是这个工程的核心,java与c++代码都这里。
- realm-annotations模块是realm使用到的注解,如PrimaryKey
- realm-transformer模块是在编译时辅助生成realm代码,非常重要的模块。
Realm初始化
使用Realm的第一步是调用Realm.init(this),源码如下:
public static synchronized void init(Context context) { if (BaseRealm.applicationContext == null) { if (context == null) { throw new IllegalArgumentException("Non-null context required."); } // 检查是否能范围应用的数据存储空间的目录 checkFilesDirAvailable(context); // 加载 librealm-jni.so RealmCore.loadLibrary(context); // 关键点:设置Realm默认配置 setDefaultConfiguration(new RealmConfiguration.Builder(context).build()); ObjectServerFacade.getSyncFacadeIfPossible().init(context); BaseRealm.applicationContext = context.getApplicationContext(); SharedRealm.initialize(new File(context.getFilesDir(), ".realm.temp")); }}
Realm配置封装在RealmConfiguration,以Builder模式实现定制化需求。先看RealmConfiguration.Builder的build方法,源码如下:
public RealmConfiguration build() { //忽略前面的合法性判断 return new RealmConfiguration(directory, fileName, getCanonicalPath(new File(directory, fileName)), assetFilePath, key, schemaVersion, migration, deleteRealmIfMigrationNeeded, durability, createSchemaMediator(modules, debugSchema), rxFactory, initialDataTransaction, readOnly, compactOnLaunch ); }
从上面的build方法来看,参数的传递需要从Builder构造方法来追踪,继续查看Builder的构造方法源码:
{ public Builder() { this(BaseRealm.applicationContext); } Builder(Context context) { if (context == null) { throw new IllegalStateException("Call `Realm.init(Context)` before creating a RealmConfiguration"); } RealmCore.loadLibrary(context); initializeBuilder(context); } private void initializeBuilder(Context context) { this.directory = context.getFilesDir(); this.fileName = Realm.DEFAULT_REALM_NAME; this.key = null; this.schemaVersion = 0; this.migration = null; this.deleteRealmIfMigrationNeeded = false; this.durability = SharedRealm.Durability.FULL; this.readOnly = false; this.compactOnLaunch = null; if (DEFAULT_MODULE != null) { this.modules.add(DEFAULT_MODULE); } }}
从initializeBuilder可以确定,Builder已经为RealmConfiguration配置项提供了默认值,比如指定了存储位置、文件名、版本号等。其中modules这属性是关键点,因为它是后面构造RealmProxyMediator实例的关键。先看这个DEFAULT_MODULE,相关源码如下:
private static final Object DEFAULT_MODULE;protected static final RealmProxyMediator DEFAULT_MODULE_MEDIATOR;//没想到居然是以静态代码块的方式来实例化的。static { DEFAULT_MODULE = Realm.getDefaultModule(); if (DEFAULT_MODULE != null) { final RealmProxyMediator mediator = getModuleMediator(DEFAULT_MODULE.getClass().getCanonicalName()); if (!mediator.transformerApplied()) { throw new ExceptionInInitializerError("RealmTransformer doesn't seem to be applied." + " Please update the project configuration to use the Realm Gradle plugin." + " See https://realm.io/news/android-installation-change/"); } DEFAULT_MODULE_MEDIATOR = mediator; } else { DEFAULT_MODULE_MEDIATOR = null; }}
往下继续追踪Realm.getDefaultModule(),如下源码:
public static Object getDefaultModule() { //看到这里时,就跟Realm编译时自动生成的代码对应上了 String moduleName = "io.realm.DefaultRealmModule"; Class<?> clazz; //noinspection TryWithIdenticalCatches try { clazz = Class.forName(moduleName); Constructor<?> constructor = clazz.getDeclaredConstructors()[0]; constructor.setAccessible(true); return constructor.newInstance(); } catch (ClassNotFoundException e) { return null; } catch (InvocationTargetException e) { throw new RealmException("Could not create an instance of " + moduleName, e); } catch (InstantiationException e) { throw new RealmException("Could not create an instance of " + moduleName, e); } catch (IllegalAccessException e) { throw new RealmException("Could not create an instance of " + moduleName, e); }}
DefaultRealmModule ,Realm默认配置下时会是空类
package io.realm;@io.realm.annotations.RealmModule(allClasses = true)class DefaultRealmModule {}
前面的源码来看,通过反射构造了DefaultRealmModule实例,它会被用于DEFAULT_MODULE_MEDIATOR的初始化,回到4中的静态代码块,看看getModuleMediator是如何构造DEFAULT_MODULE_MEDIATOR,源码如下:
// 代码比较简单,就是反射实例化DefaultRealmModuleMediatorprivate static RealmProxyMediator getModuleMediator(String fullyQualifiedModuleClassName) { String[] moduleNameParts = fullyQualifiedModuleClassName.split("\\."); String moduleSimpleName = moduleNameParts[moduleNameParts.length - 1]; String mediatorName = String.format(Locale.US, "io.realm.%s%s", moduleSimpleName, "Mediator"); Class<?> clazz; //noinspection TryWithIdenticalCatches try { clazz = Class.forName(mediatorName); Constructor<?> constructor = clazz.getDeclaredConstructors()[0]; constructor.setAccessible(true); return (RealmProxyMediator) constructor.newInstance(); } catch (ClassNotFoundException e) { throw new RealmException("Could not find " + mediatorName, e); } catch (InvocationTargetException e) { throw new RealmException("Could not create an instance of " + mediatorName, e); } catch (InstantiationException e) { throw new RealmException("Could not create an instance of " + mediatorName, e); } catch (IllegalAccessException e) { throw new RealmException("Could not create an instance of " + mediatorName, e); }}
当最关键的modules初始化完毕,再回去看2中的build方法了,就知道createSchemaMediator是如何构造RealmProxyMediator的,源码如下:
protected static RealmProxyMediator createSchemaMediator(Set<Object> modules, Set<Class<? extends RealmModel>> debugSchema) { // 调试用途,注意DEFAULT_MODULE_MEDIATOR仅被debugSchema使用 if (debugSchema.size() > 0) { return new FilterableMediator(DEFAULT_MODULE_MEDIATOR, debugSchema); } // 默认配置,见到了上面的getModuleMediator方法,至此会构建DefaultRealmModuleMediator实例 if (modules.size() == 1) { return getModuleMediator(modules.iterator().next().getClass().getCanonicalName()); } // Otherwise combines all mediators. RealmProxyMediator[] mediators = new RealmProxyMediator[modules.size()]; int i = 0; for (Object module : modules) { mediators[i] = getModuleMediator(module.getClass().getCanonicalName()); i++; } return new CompositeMediator(mediators);}
上面其实就是实例化了DefaultRealmModuleMediator,那么这个由代码自动生成的类究竟为何物,因篇幅有限,仅贴如下几行:
@io.realm.annotations.RealmModuleclass DefaultRealmModuleMediator extends RealmProxyMediator {private static final Set<Class<? extends RealmModel>> MODEL_CLASSES;static { Set<Class<? extends RealmModel>> modelClasses = new HashSet<Class<? extends RealmModel>>(); // 这些就是一个个对应的RealmObject modelClasses.add(com.example.app.org.realm.threads.model.User.class); modelClasses.add(com.example.app.org.realm.demo.Dog.class); modelClasses.add(com.example.app.org.realm.threads.model.Person.class); MODEL_CLASSES = Collections.unmodifiableSet(modelClasses);}@Overridepublic Map<Class<? extends RealmModel>, OsObjectSchemaInfo> getExpectedObjectSchemaInfoMap() { infoMap.put(com.example.app.org.realm.threads.model.User.class, io.realm.UserRealmProxy.getExpectedObjectSchemaInfo()); infoMap.put(com.example.app.org.realm.demo.Dog.class, io.realm.DogRealmProxy.getExpectedObjectSchemaInfo()); infoMap.put(com.example.app.org.realm.threads.model.Person.class, io.realm.PersonRealmProxy.getExpectedObjectSchemaInfo()); return infoMap;}@Overridepublic ColumnInfo validateTable(Class<? extends RealmModel> clazz, SharedRealm sharedRealm, boolean allowExtraColumns) { checkClass(clazz); if (clazz.equals(com.example.app.org.realm.threads.model.User.class)) { return io.realm.UserRealmProxy.validateTable(sharedRealm, allowExtraColumns); } if (clazz.equals(com.example.app.org.realm.demo.Dog.class)) { return io.realm.DogRealmProxy.validateTable(sharedRealm, allowExtraColumns); } if (clazz.equals(com.example.app.org.realm.threads.model.Person.class)) { return io.realm.PersonRealmProxy.validateTable(sharedRealm, allowExtraColumns); } throw getMissingProxyClassException(clazz);}@Overridepublic List<String> getFieldNames(Class<? extends RealmModel> clazz) { checkClass(clazz); if (clazz.equals(com.example.app.org.realm.threads.model.User.class)) { return io.realm.UserRealmProxy.getFieldNames(); } if (clazz.equals(com.example.app.org.realm.demo.Dog.class)) { return io.realm.DogRealmProxy.getFieldNames(); } if (clazz.equals(com.example.app.org.realm.threads.model.Person.class)) { return io.realm.PersonRealmProxy.getFieldNames(); } throw getMissingProxyClassException(clazz);}}... ...
public class User extends RealmObject { private String name; private int age; @Ignore private int sessionId; // 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 sessionId) { this.sessionId = sessionId; }}
继续看DefaultRealmModuleMediator的父类RealmProxyMediator的源码,发现它定义了一套Realm数据库的读写相关操作的抽象方法,而DefaultRealmModuleMediator则是负责实现这些方法,其源码如下:
public abstract class RealmProxyMediator { public abstract Map<Class<? extends RealmModel>, OsObjectSchemaInfo> getExpectedObjectSchemaInfoMap(); public abstract ColumnInfo validateTable(Class<? extends RealmModel> clazz,SharedRealm sharedRealm,boolean allowExtraColumns); public abstract List<String> getFieldNames(Class<? extends RealmModel> clazz); public abstract String getTableName(Class<? extends RealmModel> clazz); public abstract <E extends RealmModel> E newInstance(Class<E> clazz,Object baseRealm,Row row,ColumnInfo columnInfo,boolean acceptDefaultValue,List<String> excludeFields); public abstract Set<Class<? extends RealmModel>> getModelClasses(); public abstract <E extends RealmModel> E copyOrUpdate(Realm realm, E object, boolean update, Map<RealmModel,RealmObjectProxy> cache); public abstract void insert(Realm realm, RealmModel object, Map<RealmModel, Long> cache); public abstract void insertOrUpdate(Realm realm, RealmModel object, Map<RealmModel, Long> cache); public abstract void insertOrUpdate(Realm realm, Collection<? extends RealmModel> objects); public abstract void insert(Realm realm, Collection<? extends RealmModel> objects); public abstract <E extends RealmModel> E createOrUpdateUsingJsonObject(Class<E> clazz, Realm realm, JSONObject json, boolean update) throws JSONException; public abstract <E extends RealmModel> E createUsingJsonStream(Class<E> clazz, Realm realm, JsonReader reader) throws java.io.IOException; public abstract <E extends RealmModel> E createDetachedCopy(E realmObject, int maxDepth, Map<RealmModel,RealmObjectProxy.CacheData<RealmModel>> cache); ... ...}
以上就是Realm的初始化最主要过程,简单可概况为Realm初始化过程为数据库的读写等操作部署好了环境。
- Realm源码分析之初始化
- Shiro源码分析-初始化-Realm
- Realm源码分析之Writes
- shiro源码分析之Realm调用过程
- Realm源码分析之copyToRealm与copyToRealmOrUpdate
- Realm源码分析之自动更新原理
- velocity源码分析:初始化之指令初始化
- arm-linux源码分析之cpu初始化
- velocity源码分析:初始化之配置文件
- velocity源码分析:初始化之日志系统
- velocity源码分析:初始化之ResourceManager
- COCOS2D-X源码分析之初始化游戏
- Raw-OS源码分析之系统初始化
- nginx源码分析之网络初始化
- shiro源码分析之shiroFilter初始化过程
- NFC源码分析之初始化流程
- DDR2初始化源码分析
- Application初始化源码分析
- Hibernate基本概念及开发环境的搭建
- ajax传多个实体参数到后端controller
- Eva's Balance
- win10中微软账户中文名称修改后本地用户文件夹仍为中文名
- java poi 解析excel 输出json 并且拼接字符串显示到jsp
- Realm源码分析之初始化
- leetcode[Arranging Coins]
- [bzoj2946][后缀数组][Poi2000]公共串
- mongoDB的使用
- 【剑指offer】面试题26:树的子结构
- 将form表单封装成对象
- platform_set_drvdata 和 platform_get_drvdata
- 三级联动
- HDU