美文网首页
realm学习

realm学习

作者: 誰許誰天荒 | 来源:发表于2017-02-09 10:04 被阅读0次
    为什么用realm

    android开发不仅仅是从网上获取数据并且展示,有时候我们需要把数据保存到我们本地,一般我们会想到用file,sp或者数据库sqlite,file的方式主要是IO流操作,sp是其实是使用xml的方式以键值对形式存储基本数据类型的数据。但是对于app中有复杂筛选查询的操作,file和sp都不能满足了.虽然sqlite可以满足有大量复杂查询要求的缓存数据操作。但是sqlite的使用略复杂,代码量很大.这时候就需要一种轻量级的数据库.Realm是一个可以替代SQLite以及ORM Libraries的轻量级数据库。

    realm的优势
    • 相比SQLite,Realm更快并且具有很多现代数据库的特性,比如除了基本数据类型之外,还支持JSON.流式api,数据变更通知,以及加密支持
    • realm是一个跨平台移动数据库引擎,支持iOS、OS X(Objective-C和Swift)以及Android。这些都为移动端开发者带来了方便。
    • 性能比较高
    • 使用简单
    使用方法

    1.在项目的build.grade中配置

    apply plugin: 'realm-android'
    buildscript {
        repositories {
            jcenter()
            maven { url 'https://jitpack.io' }
        }
        dependencies {
            classpath "io.realm:realm-gradle-plugin:1.0.0"
        }
    }
    

    2.初始化Realm,并进行相关配置.(Realm是框架的核心所在,是我们构建数据库的访问点,使用建造者模式构建对象。)

    默认配置,

    public class MyApplication extends Application {
      @Override
      public void onCreate() {
        super.onCreate();
        // The Realm file will be located in Context.getFilesDir() with name "default.realm"
        Realm.init(this);//初始化realm
        RealmConfiguration config = new RealmConfiguration.Builder().build();//默认配置
        Realm.setDefaultConfiguration(config);
      }
    }
    

    自定义配置

        public class MyApplication extends Application {
      @Override
      public void onCreate() {
        super.onCreate();
        Realm.init(this);//初始化
        //自定义配置
        RealmConfiguration config = new  RealmConfiguration.Builder()
                                             .name("myRealm.realm")
                                             .deleteRealmIfMigrationNeeded()
                                             .build();
        Realm.setDefaultConfiguration(config);
      }
    }
    

    3.创建实体RealmObject(这是我们自定义的realm数据模型。创建数据模型的行为将会影响到数据库的结构。要创建一个数据模型,我们只需要继承RealmObject,然后设计我们想要存储的属性即可。)

    public class Dog extends RealmObject {
    private String name;
    private int age;
    
    @PrimaryKey
    private String id;
    
    
    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 String getId() {
        return id;
    }
    
    public void setId(String id) {
        this.id = id;
    }
    }
    

    4.增

    a.使用事务操作,新建一个对象,并且进行存储
    Realm realm=Realm.getDefaultInstance();

    realm.beginTransaction();//开启一个事务
    User user = realm.createObject(User.class); //创建一个对象
    user.setName("John");
    user.setEmail("john@corporation.com");
    realm.commitTransaction();//提交事务
    

    b.使用事务块
    Realm mRealm=Realm.getDefaultInstance();

    final User user = new User("John");//创建对象
    user.setEmail("john@corporation.com");
    
    mRealm.executeTransaction(new Realm.Transaction() {//事务块
                @Override
                public void execute(Realm realm) {
                
                realm.copyToRealm(user);
                   
                }
            });
    

    5.删. (RealmResults:这个类是执行任何查询请求后所返回的类,其中包含了一系列的Object对象。和List类似,我们可以用下标语法来对其进行访问,并且还可以决定它们之间的关系。不仅如此,它还拥有许多更强大的功能,包括排序、查找等等操作。
    )

    Realm  mRealm=Realm.getDefaultInstance();
    
    final RealmResults<Dog> dogs=  mRealm.where(Dog.class).findAll();
    
        mRealm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
            
                Dog dog=dogs.get(5);
                dog.deleteFromRealm();
                //删除第一个数据
                dogs.deleteFirstFromRealm();
                //删除最后一个数据
                dogs.deleteLastFromRealm();
                //删除位置为1的数据
                dogs.deleteFromRealm(1);
                //删除所有数据
                dogs.deleteAllFromRealm();
            }
        });
    

    上面的代码是用事务块进行删除,跟增加操作一样,也可以用事务beginTransaction和commitTransaction方法进行删除

    6.改

    RealmObject是自动更新的,比如你将一个数据读取出来后,又做了修改,修改会马上在数据中生效,不需要你再
    将数据保存到数据库

    Realm  mRealm=Realm.getDefaultInstance();
    
    Dog dog = mRealm.where(Dog.class).equalTo("id", id).findFirst();
    mRealm.beginTransaction();
    dog.setName(newName);
    mRealm.commitTransaction();
    

    也可以用事务块来进行修改

    7.查

    a.查询全部

     public List<Dog> queryAllDog() {
            Realm  mRealm=Realm.getDefaultInstance();
        
            RealmResults<Dog> dogs = mRealm.where(Dog.class).findAll();
            
            return mRealm.copyFromRealm(dogs);
        }
    

    b.条件查询

      public Dog queryDogById(String id) {
        Realm  mRealm=Realm.getDefaultInstance();
    
        Dog dog = mRealm.where(Dog.class).equalTo("id", id).findFirst();
        return dog;
    }
    

    还有其他的条件:

    • between(), greaterThan(), lessThan(), greaterThanOrEqualTo() & lessThanOrEqualTo()

    • equalTo() & notEqualTo()

    • contains(), beginsWith() & endsWith()

    • isNull() & isNotNull()

    • isEmpty() & isNotEmpty()

    8.使用realm来操作数据库,尽管这些操作很快,但是还是建议放在后台进行。可以在回调中更新ui

    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.  
            }  
        });
    

    最后,我们要及时关闭realm任务,避免程序crash

    public void onDestroy () {  
    if (transaction != null && !transaction.isCancelled()) {  
        transaction.cancel();  
    }  
    }
    
    Realm的一些坑

    1.查询到的结果数据 不能跨线程使用.例如在主线程中查到的结果 在线程中想使用 需要在子线程中再查一次

    2.realm对象不能跨线程使用.主线程中获取的realm对象, 不能在子线程中使用.需要重新调用getDefaultInstance()在子线程中获取另一个realm对象

    3.当query到的数据要被使用时, realm数据库是要在开启的状态下的, 这样数据才能通过数据库链接访问到.在数据使用完毕后 需要把数据库关闭.一般选在在页面onDestory()的方法中 调用realm.close()方法关闭数据库链接.但如果网络请求数据的回调在页面关闭之后发生 也就是realm.close()调用了之后 又使用了同一个realm数据库链接查询数据
    此时回报错误This Realm instance has already been closed, making it unusable.
    解决办法是
    如果还想使用同一个realm链接
    先判断realm.isClosed()
    数据库链接是否关闭了 如果关闭了重新打开一个新的数据库链接 使用完之后再将新的数据库链接关闭

    4.如果想在Realm.close()之后继续操作查询得到的对象,只能复制一份数据传出来.

    5.如果直接修改或删除query得到的数据,必须在transaction中完成.

    相关文章

      网友评论

          本文标题:realm学习

          本文链接:https://www.haomeiwen.com/subject/xwkiittx.html