Realm 移动端数据库

Realm 移动端数据库快速、易用、开源且完全免费,深受开发者和亿万用户喜爱。

简单、快速,节约数周的开发时间。

简单、快速,节约数周的开发时间。

Realm 是 SQLite 和 Core Data 的替代者,得益于其零拷贝的设计,Realm 比任何 ORM 都要快很多。几分钟内就能学会使用 Realm。

专为移动设备打造的数据库

离线优先

离线优先

即使在离线状态下你的应用也可正常工作

查询快速

查询快速

复杂查询也只需要几纳秒,查询结果与新数据实时同步

线程安全

线程安全

多线程访问同一数据毫无问题

跨平台支持

跨平台支持

多个平台不同应用使用同一数据库

加密

加密

无需额外代码,就能保证你的数据安全

响应式架构

响应式架构

让 Realm 连接到 UI,及时将数据更新反馈给用户

class Dog {}

Dog.schema = {
  name: 'Dog',
  properties: {
    name: 'string',
    age: 'int',
  }
};

let realm = new Realm({ schema: [Dog] });
realm.write(() => {
  realm.create('Dog', {name: 'Rex', age: 1});
});

let pups = realm.objects('Dog').filtered('age < 2');
Dog *dog = [Dog new];
dog.name = @"Rex";
dog.age = 1;

RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
  [realm addObject:dog];
}];

RLMResults<Dog *> *allDogs = [Dog allObjects];
RLMResults<Dog *> *pups = [allDogs objectsWhere:@"age < 2"];
class Dog: Object {
  dynamic var name = ""
  dynamic var age = 0
}

let dog = Dog()
dog.name = "Rex"
dog.age = 1

let realm = try! Realm()
try! realm.write {
  realm.add(dog)
}

let pups = realm.objects(Dog.self).filter("age < 2")
public class Dog extends RealmObject {
  public String name;
  public int age;
}

Dog dog = new Dog();
dog.name = "Rex";
dog.age = 1;

Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
realm.copyToRealm(dog);
realm.commitTransaction();

RealmResults<Dog> pups = realm.where(Dog.class)
                               .lessThan("age", 2)
                               .findAll();
public class Dog : RealmObject 
{
  public string Name { get; set; }
  public int Age { get; set; }
}

var realm = Realm.GetInstance();
realm.Write(() => 
{
  realm.Add(new Dog
  {
    Name = "Rex",
    Age = 1
  });
});

var pups = realm.All<Dog>().Where(d => d.Age < 2);

简化你的代码

只需 继承 RealmObject 定义你的 schema, 继承 RLMObject 定义你的 schema, 定义你的 schema, 继承 Object 定义你的 schema, 继承 RealmObject 定义你的 schema, 使用 Realm 的轻量级事务将对象持久化,然后通过 函数接口 NSPredicate 简单的字符串 NSPredicate LINQ 进行查询。操作你的数据就是这么简单。

React Native executes JavaScript in a dedicated worker thread so common concurrency primitives are unavailable.
// Query and update the result in another thread
dispatch_async(dispatch_queue_create("background", 0), ^{
  Dog *theDog = [[Dog objectsWhere:@"age == 1"] firstObject];
  RLMRealm *realm = [RLMRealm defaultRealm];
  [realm beginWriteTransaction];
  theDog.age = 3;
  [realm commitWriteTransaction];
});
// Query and update from any thread
DispatchQueue(label: "background").async {
  let realm = try! Realm()
  let theDog = realm.objects(Dog.self).filter("age == 1").first
  try! realm.write {
    theDog!.age = 3
  }
}
public void onActivityCreated(Bundle savedInstanceState) {
  realm = Realm.getDefaultInstance();
  customers = realm.where(Customer.class).findAllAsync();
  changeListener = new RealmChangeListener() {
    @Override
    public void onChange(RealmResults<Customer> results) {
      listAdapter.notifyDataSetChanged(); // Update the UI
    }
  };
  customers.addChangeListener(changeListener);
}
// Query and update from any thread
Task.Run(() =>
{
  var realm = Realm.GetInstance();
  var theDog = realm.All<Dog>().First(d => d.Age == 1);
  realm.Write(() => theDog.Age = 3);
});

多线程访问

只要在新线程中获得一个新 Realm 实例,剩下的事情就无需操心。每次读取都会得到一致的数据。

let key = new Int8Array(64);  // pupulate with a secure key

let realm = new Realm({ schema: [Dog], encryptionKey: key });

let dogs = realm.objects('Dog').filtered('name CONTAINS "Fido"');
// Generate a random encryption key
NSMutableData *key = [NSMutableData dataWithLength:64];
(void)SecRandomCopyBytes(kSecRandomDefault, key.length, (uint8_t *)key.mutableBytes);

// Open the encrypted Realm file
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.encryptionKey = key;
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
// Use the Realm as normal
RLMResults<Dog *> *dogs = [Dog objectsInRealm:realm where:@"name contains 'Fido'"];
// Generate a random encryption key
var key = Data(count: 64)
_ = key.withUnsafeMutableBytes { bytes in
  SecRandomCopyBytes(kSecRandomDefault, 64, bytes)
}

// Open the encrypted Realm file
let realm = try! Realm(configuration: Realm.Configuration(encryptionKey: key))
// Use the Realm as normal
let dogs = realm.objects(Dog.self).filter("name contains 'Fido'")
// Generate a random encryption key
byte[] key = new byte[64];
new SecureRandom().nextBytes(key);

// Open the encrypted Realm file
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder()
        .encryptionKey(key)
        .build();

// Use the Realm as normal
Realm realm = Realm.getInstance(config);
RealmResults<Dog> results = realm.where(Dog.class).contains("name", "Fido").findAll();
// Generate a random encryption key
var random = new Random();
var key = new Byte[64];
rnd.NextBytes(key);
var config = new RealmConfiguration("Mine.realm");
config.EncryptionKey = key;

// Open the encrypted Realm file
var realm = Realm.GetInstance(config);
// Use the Realm as normal
var dogs = realm.All<Dog>().Where(d => d.Name.Contains("Fido"));

加密一切

通过 AES-256(本地数据)加密用户数据,即使针对财务系统也足以胜任。

let realm = new Realm({ schema: [Person] });
realm.addListener((sender, name) => {
  if (name === 'change') {
    this.setState({ source: sender.objects('Dog') });
  }
});
self.notificationToken = [[Dog objectsWhere:@"age > 5"]
                            addNotificationBlock:^(RLMResults<Dog *> *results,
                                                   RLMCollectionChange *change,
                                                   NSError *error) {
  if (error) {
    // handle error
    return;
  } else if (!changes) {
    [self.tableView reloadData];
    return;
  }

  // Update table view to animate deletions, insertions and modifications
  [tableView beginUpdates];
  [tableView deleteRowsAtIndexPaths:[changes deletionsInSection:0]
    withRowAnimation:UITableViewRowAnimationAutomatic];
  [tableView insertRowsAtIndexPaths:[changes insertionsInSection:0]
    withRowAnimation:UITableViewRowAnimationAutomatic];
  [tableView reloadRowsAtIndexPaths:[changes modificationsInSection:0]
    withRowAnimation:UITableViewRowAnimationAutomatic];
  [tableView endUpdates];
}];
let realm = try! Realm()
notificationToken = realm.objects(Dog.self).filter("age > 5").addNotificationBlock { changes in
  switch changes {
  case .initial:
    tableView.reloadData()
    break
  case .update(_, let deletions, let insertions, let modifications):
    // Update table view to animate deletions, insertions and modifications
    break
  case .error(let error):
    // handle error
    break
  }
}
Realm realm = Realm.getDefaultInstance();

// Query in the background
RealmResults<Dog> results = realm.where(Dog.class)
  .greaterThan("age", 5)
  .findAllAsync();

// Use ChangeListeners to be notified about updates
results.addChangeListener(new RealmChangeListener<RealmResults<Dog>() {
  @Override
  public void onChange(RealmResults<Dog> results) {
    // Update UI
  }
});

// Or RxJava
Observable<RealmResults<Dog>> obs = results.asObservable();
// To bind a ListView to results of a query
public partial class DogsPage : ContentPage
{
  internal Realm realm;
  internal IEnumerable<Dog> Entries { get; }

  public DogsPage()
  {
    InitializeComponent();
    realm = Realm.GetInstance();

    // Results from queries will automatically notify the Binding
    // and update the ListView accordingly
    Entries = realm.All<Dog>().Where(d => d.Age > 5)
    DogsList.ItemsSource = Entries;
  }

<ListView x:Name="DogsList">
  <ListView.ItemTemplate>
    <DataTemplate>
      <TextCell Text="{Binding Name}" 
        Detail="{Binding Age, StringFormat='is {0:#}'}" /> 
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

创建响应式应用

Realm 对象是实时更新的,通过订阅数据更新通知来刷新 UI, 让你的应用界面永远不会过时。

// Authenticating the User
Realm.Sync.User.registerWithProvider('http://realm.example.co:9080', 'google', googleAccessToken, (error, user) => {
  if (!error) {
    // Opening a remote Realm
    var realm = new Realm({
      sync: {
        user: user,
        url: 'realm://realm.example.co:9080/~/userRealm',
      }
    });
    // Any changes made to this Realm will be synced across all devices!
  }
})
// Authenticating the User
[RLMSyncUser logInWithCredentials:[RLMSyncCredentials credentialsWithGoogleToken:@"google token"]
                    authServerURL:[NSURL URLWithString:@"http://realm.example.com:9080"]
                     onCompletion:^(RLMSyncUser *user, NSError *error) {
  if (user) {
    // Opening a remote Realm
    NSURL *realmURL = [NSURL URLWithString:@"realm://realm.example.com:9080/~/userRealm"];
    RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
    config.syncConfiguration = [[RLMSyncConfiguration alloc] initWithUser:user realmURL:realmURL];
    RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
    // Any changes made to this Realm will be synced across all devices!
  } else if (error) {
    // handle error
  }
}];
// Authenticating the User
SyncUser.logIn(with: .google(token: "google token"),
               server: URL(string: "http://realm.example.com:9080")!) { user, error in
  if let user = user {
    // Opening a remote Realm
    let realmURL = URL(string: "realm://realm.example.com:9080/~/userRealm")!
    let config = Realm.Configuration(syncConfiguration: SyncConfiguration(user: user, realmURL: realmURL))
    let realm = try! Realm(configuration: config)
    // Any changes made to this Realm will be synced across all devices!
  } else if let error = error {
    // handle error
  }
}
// Authenticating the User
User user = User.login(Credentials.google("google token"),
                       "http://realm.example.com:9080/auth");
// Opening a remote Realm
String realmURL = "realm://realm.example.com:9080/~/userRealm";
SyncConfiguration config = new SyncConfiguration.Builder(user,
                                                         realmURL).build();
Realm realm = Realm.getInstance(config);
// Any changes made to this Realm will be synced across all devices!
var user = await User.LoginAsync(Credentials.Google("google token"),
                                 new Uri("http://realm.example.com:9080"));

var realmUrl = new Uri("realm://realm.example.com:9080/~/userRealm");
var config = new SyncConfiguration(user, realmUrl);

var realm = Realm.GetInstance(config);
// Any changes made to this Realm will be synced across all devices!

无缝同步数据

通过 Realm 移动端平台扩展,Realm 移动端数据库可以与 Realm 对象服务完美协同工作。你所需的仅仅是配置 Realm 对象服务的 URL,其它操作与之前完全一样。数据同步在存储数据时自动进行,无需任何其它操作。

该功能现被 Realm JavaRealm Objective‑CRealm Swift 所支持。Realm React Native 与 Realm Xamarin 也即将支持。

开源

Realm 移动端数据库相关代码已全部开源。数千开发者在 GitHub 上参与了相关工作。另外还有几百个 Realm 数据库相关的扩展。Realm 仓库的总计两万五千个星标说明了一切。

获取更多移动开发的信息

通过邮件获取最新文章。还可以看看我们已经发布的新闻



财富500强和 app 商店里的优秀应用,都信任 Realm。每天都有亿万人在使用基于 Realm 创建的 app。

分分钟了解如何在 app 中保存数据