Realm源码分析之初始化

来源:互联网 发布:access vba编程入门 编辑:程序博客网 时间:2024/05/29 17:31

Realm源码下载

  1. 上篇Realm总结是关于Realm的基础使用,可粗略地概括为如下关系图:
    这里写图片描述

  2. 在感受了Realm的强大之后,更让人对其背后的实现原理感到好奇,点击下载Realm源码一探究竟吧。

  3. 目前Realm java的版本是3.5,如下工程截图,模块简介如下:
    这里写图片描述 这里写图片描述

    1. realm-java工程囊括了好几个模块,而编译配置说明是在工程根目录下的README.md
    2. examples模块是realm提供的使用demo
    3. gradle-plugin模块是realm编译使用的插件
    4. realm模块则是这个工程的核心,java与c++代码都这里。
    5. realm-annotations模块是realm使用到的注解,如PrimaryKey
    6. realm-transformer模块是在编译时辅助生成realm代码,非常重要的模块。

Realm初始化

  1. 使用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"));    }}
  2. 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        );    }
  3. 从上面的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);        }    }}
  4. 从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;    }}
  5. 往下继续追踪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);    }}

    这里写图片描述

  6. DefaultRealmModule ,Realm默认配置下时会是空类

    package io.realm;@io.realm.annotations.RealmModule(allClasses = true)class DefaultRealmModule {}
  7. 前面的源码来看,通过反射构造了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);    }}
  8. 当最关键的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);}
  9. 上面其实就是实例化了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; }}
  10. 继续看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);    ... ...}
  11. 以上就是Realm的初始化最主要过程,简单可概况为Realm初始化过程为数据库的读写等操作部署好了环境。

原创粉丝点击