最后
在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
buildscript {
repositories {
jcenter()
}
dependencies {
classpath “io.realm:realm-gradle-plugin:2.3.0”
}
}
然后在app的build.gradle文件中添加:
apply plugin: ‘realm-android’
Done.
Models
Model类只要继承RealmObject
即可.
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; } }
字段类型
Model类中可以包含的字段类型包括基本数据类型(及它们的装箱类型)和Date类, 另外也可以包含RealmObject
的子类或者是RealmList<? extends RealmObject>
.
字段性质
在字段上加注解可以定义字段的性质:
@Required
表明字段非null.
原生类型和RealmList
类型默认是非null的.
RealmObject
字段永远是可以为null的.
@Ignore
表示字段不会被存储.
@Index
加索引.
@PrimaryKey
加主键, 主键只能有一个, 主键默认加索引.
但是注意主键默认没有加@Required
, 如果主键要求非null, 需要显式添加@Required
.
主键使用
有主键才能使用copyToRealmOrUpdate()
这个方法.
主键类型必须是String或者整型(byte, short, int, long)或者它们的装箱类型(Byte, Short, Integer, Long).
有主键的对象创建的时候不能使用createObject(Class<E> clazz)
方法, 而应该使用createObject(Class<E> clazz, Object primaryKeyValue)
附上主键.
或者用
copyToRealm(obj)
或copyToRealmOrUpdate(obj)
, 前者遇到主键冲突时会崩溃, 后者遇到主键冲突会更新已有对象.
自动更新的对象
Realm中的数据对象是自动更新(Auto-Updating)的, 对象一旦被查询出来, 后续发生的任何数据改变也会立即反映在结果中, 不需要刷新对象.
这是一个非常有用的特性, 结合数据变化的通知可以很方便地刷新UI.
关系
–
Realm model对象间可以很方便地建立关系.
你可以在Model中存储另一个对象的引用, 建立多对一的关系; 也可以存储一组对象RealmList<T>
, 建立一对多或多对多的关系.
RealmList<T>
的getter永远也不会返回null, 它只会返回一个为空的list.
把这个字段设置为null可以清空这个list.
初始化
Realm在使用之前需要调用初始化:
Realm.init(context);
建议把它放在Application的onCreate()
里.
配置
配置类: RealmConfiguration
定义了Realm的创建配置.
最基本的配置:
RealmConfiguration config = new RealmConfiguration.Builder().build();
它会创建一个叫default.realm
的文件, 放在Context.getFilesDir()
的目录下.
如果我们想自定义一个配置, 可以这样写:
// The RealmConfiguration is created using the builder pattern. // The Realm file will be located in Context.getFilesDir() with name “myrealm.realm” RealmConfiguration config = new RealmConfiguration.Builder() .name(“myrealm.realm”) .encryptionKey(getKey()) .schemaVersion(42) .modules(new MySchemaModule()) .migration(new MyMigration()) .build(); // Use the config Realm realm = Realm.getInstance(config);
所以我们是可以有多个配置, 访问多个Realm实例的.
我们可以把配置设置为默认配置:
Realm.init(this); RealmConfiguration config = new RealmConfiguration.Builder().build(); Realm.setDefaultConfiguration(config);
之后用Realm.getDefaultInstance()
取到的就是这个默认配置对应的实例.
数据库迁移
迁移的策略是通过config指定的:
RealmConfiguration config = new RealmConfiguration.Builder() .schemaVersion(2) // Must be bumped when the schema changes .migration(new MyMigration()) // Migration to run instead of throwing an exception .build()
其中MyMigration
实现了RealmMigration
接口, 在migrate()
方法中根据新旧版本号进行一步一步地升级.
具体例子见Migration.
开发的时候为了方便我用的是.deleteRealmIfMigrationNeeded()
, 这样在需要数据库迁移的时候直接就删了数据重新开始了.
关于Realm的close()
一个打开的Realm实例会持有一些资源, 有一些是Java不能自动管理的, 所以就需要打开实例的代码负责在不需要的时候将其关闭.
Realm的instance是引用计数的(reference counted cache), 在同一个线程中获取后续实例是免费的, 但是底层的资源只有当所有实例被释放了之后才能释放. 也即你调用了多少次getInstance()
, 就需要调用相应次数的close()
方法.
比较建议的方法是在Activity或Fragment的生命周期中处理Realm实例的开启和释放:
-
在Activity的
onCreate()
中getInstance()
,onDestroy()
中close()
. -
在Fragment的
onCreateView()
中getInstance()
,onDestroyView()
中close()
.
如果多个Fragment相关的都是同一个数据库实例, 那么在Activity中处理更好一些.
写
写操作一般的流程是这样:
// Obtain a Realm instance Realm realm = Realm.getDefaultInstance(); realm.beginTransaction(); //… add or update objects here … realm.commitTransaction();
这里创建对象可以用createObject()
方法或者copyToRealm()
方法.
前者是先创建再set值, 后者是先new对象再更新数据库.
如果不想自己处理beginTransaction()
, cancelTransaction()
和commitTransaction()
, 可以直接调用realm.executeTransaction()
方法:
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”); } });
异步
因为transactions之间是互相阻塞的.
异步执行可以用这个方法:
realm.executeTransactionAsync(new Realm.Transaction() { @Override public void execute(Realm bgRealm) { User user = bgRealm.createObject(User.class); user.setName(“John”); user.setEmail(“john@corporation.com”); } }, new Realm.Transaction.OnSuccess() { @Override public void onSuccess() { // Transaction was a success. } }, new Realm.Transaction.OnError() { @Override public void onError(Throwable error) { // Transaction failed and was automatically canceled. } });
这两个回调是Optional的, 它们只能在有Looper的线程调用.
注意: 这个方法的返回值对象可以用于在Activity/Fragment生命周期结束的时候取消未完的操作.
删除和更新
所有的写操作都要放在transaction中进行, 如上, 不同的操作只是其中具体方法不同.
删除操作:
final RealmResults users = getUsers(); // method 1: users.get(0).deleteFromRealm(); // method 2: users.deleteFromRealm(0); // delete all users.deleteAllFromRealm();
更新操作:
realm.copyToRealmOrUpdate(obj);
注意: 这个方法需要Model有主键, 会更新obj的主键对应的对象, 如果不存在则新建对象.
查询
–
查询可以流式地写:
// Or alternatively do the same all at once (the “Fluent interface”): RealmResults result2 = realm.where(User.class) .equalTo(“name”, “John”) .or() .equalTo(“name”, “Peter”) .findAll();
最后
最后这里放上我这段时间复习的资料,这个资料也是偶然一位朋友分享给我的,里面包含了腾讯、字节跳动、阿里、百度2020-2021面试真题解析,并且把每个技术点整理成了视频和PDF(知识脉络 + 诸多细节)。
还有 高级架构技术进阶脑图、高级进阶架构资料 帮助大家学习提升进阶,这里我也免费分享给大家也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
一起互勉~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
还有 高级架构技术进阶脑图、高级进阶架构资料 帮助大家学习提升进阶,这里我也免费分享给大家也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
[外链图片转存中…(img-QjBUk3LA-1714990176840)]
[外链图片转存中…(img-RAlVSVXw-1714990176840)]
一起互勉~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!