Realm for Android详细教程

官方API:https://realm.io/docs/java/5.4.1/api/

Quick start

Overview of Realm

  • Realm
    The Realm database. The storage and transactional manager of your object persistent store. It is in charge of creating and removing instances of your RealmObjects, querying, and performing transactions. Read more.

     

  • RealmConfiguration
    A configuration object that is used to setup a specific Realm instance. Read more.

     

  • RealmObject
    The super class of all objects (models) that are to be stored in Realm. A Java object must extend RealmObject in order to be considered a RealmObjectRead more.

     

  • RealmList
    List that is used in RealmObjects to model one-to-many relationships with other RealmObjects. Read more.

     

  • RealmQuery
    An object that encapsulates a query as defined through Realms fluent query interface. Queries are executed using either the RealmQuery.findAll()RealmQuery.findFirst() or their variants. Read more.

     

  • RealmResults
    The result set of an executed RealmQuery for a given Realm. RealmResults are live, auto-updating views into the underlying data, which means results never have to be re-fetched. Read more.

将ArrayList 改为 RealmList可以解决该问题,如果某一变量不是RealmObject 类的属性,可以使用ArrayList类型。

1. model类必须extends RealmObject,所有属性必须用private修饰

2. model中支持基本数据结构:boolean, byte, short, ìnt, long, float, double, String, Dateand byte[]

3.若要使用List必须用RealmList<T>,或者继承RealmList

编写时遇到的错误:

java.lang.IllegalStateException: This Realm instance has already been closed, making it unusable.

解决方法:

 

        if(mRealm==null)             //刚开始判断是否关闭
            mRealm=Realm.getDefaultInstance();
        //使用事务块
        mRealm.beginTransaction();            
        RealmResults<Fingerprint> dogs = mRealm.where(Fingerprint.class).findAll();
        StringBuilder stringBuilder=new StringBuilder();
        for(Fingerprint temp:dogs)
            stringBuilder.append(temp.toJSON().toString()).append("\n");
        Log.i(Tag,"数据库中信息"+stringBuilder.toString());
        List<Fingerprint>tmp=mRealm.copyFromRealm(dogs);
        mRealm.commitTransaction();

        close();  //注意要及时关闭数据库

 数据库中有五个记录,但只打印了三个,原因为找出???

package besnier.wifilocator;

import android.content.Context;
import android.nfc.Tag;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.Log;

import java.util.List;

import io.realm.Realm;
import io.realm.RealmResults;

/**
 * Created by admin on 2018/9/14.
 */

public class RealmHelper {
    private final String Tag="RealmHelper";
    public static final String DB_Name="WiFi.realm";
    private Realm mRealm;
    private ToastUtil toastUtil;
    public RealmHelper(Context context) {
        Realm.init(context);
        mRealm = Realm.getDefaultInstance();
    }

    /**
     * add (增)
     */
    @RequiresApi(api = Build.VERSION_CODES.N)
    public void addFingerprint(final Fingerprint fingerprint) {
        if(mRealm==null)
            mRealm=Realm.getDefaultInstance();
        mRealm.beginTransaction();
        RealmResults<Fingerprint> mfingerprint = mRealm.where(Fingerprint.class).equalTo("location", fingerprint.getLocation()).findAll();
        for(Fingerprint temp:mfingerprint)
            Log.i(Tag+"dele",temp.toJSON().toString());
        mfingerprint.deleteAllFromRealm();
        Log.i(Tag,"successful,end delete");
        mRealm.copyToRealm(fingerprint);
        Log.i(Tag+"add",fingerprint.toJSON().toString());
        mRealm.commitTransaction();
        close();
        Log.i(Tag,"successful,end insert");
        queryAllFingerprint();
    }
    /**
     * delete (删)
     */
    public void deleteFingerprint(String location) {
        if(mRealm==null)
            mRealm=Realm.getDefaultInstance();
       final Fingerprint fingerprint = mRealm.where(Fingerprint.class).equalTo("location", location).findFirst();
        mRealm.beginTransaction();
        fingerprint.deleteFromRealm();
        mRealm.commitTransaction();
        close();
    }
    /**
     * delete (删)
     */
    public void deleteAll() {
        if(mRealm==null)
            mRealm=Realm.getDefaultInstance();
        mRealm.beginTransaction();
        RealmResults<Fingerprint> fingerprint = mRealm.where(Fingerprint.class).findAll();
        fingerprint.deleteAllFromRealm();
        mRealm.commitTransaction();
        close();
    }

    /**
     * update (改)
     */
    public void updateFingerprint(String id, String newName) {
        if(mRealm==null)
            mRealm=Realm.getDefaultInstance();
        mRealm.beginTransaction();
        Fingerprint fingerprint = mRealm.where(Fingerprint.class).equalTo("id", id).findFirst();
        fingerprint.setLocation(newName);
        mRealm.commitTransaction();
        close();
    }

    /**
     * query (查询所有)
     */
    @RequiresApi(api = Build.VERSION_CODES.N)
    public List<Fingerprint> queryAllFingerprint() {
        if(mRealm==null)
            mRealm=Realm.getDefaultInstance();
        mRealm.beginTransaction();
        RealmResults<Fingerprint> dogs = mRealm.where(Fingerprint.class).findAll();
        StringBuilder stringBuilder=new StringBuilder();
        for(Fingerprint temp:dogs)
            stringBuilder.append(temp.toJSON().toString()).append("\n");
        Log.i(Tag,"数据库中信息"+stringBuilder.toString());
        List<Fingerprint>tmp=mRealm.copyFromRealm(dogs);
        mRealm.commitTransaction();
        close();
        return tmp;
    }

    /**
     * query (根据Id(主键)查)
     */
    public Fingerprint queryFingerprintById(String location) {
        if(mRealm==null)
            mRealm=Realm.getDefaultInstance();
        mRealm.beginTransaction();
        Fingerprint fingerprint = mRealm.where(Fingerprint.class).equalTo("id", location).findFirst();
        mRealm.commitTransaction();
        close();
        return fingerprint;
    }




    public boolean isFingerprintExist(String location){
      /*  Fingerprint fingerprint=mRealm.where(Fingerprint.class).equalTo("id",location).findFirst();
        if (fingerprint==null){
            return false;
        }else {
            return  true;
        }*/
        return  true;
    }

    public Realm getRealm(){

        return mRealm;
    }

    public void close(){
        if (mRealm!=null){
            mRealm.close();
            mRealm=null;
        }
    }
}

 

 

 

目录
1、Realm简介
2、环境配置
3、在Application中初始化Realm
4、创建实体
5、增删改查
6、异步操作
7、数据迁移(版本升级)
Demo地址(https://github.com/RaphetS/DemoRealm

增删查

![异步删](http://upload-images.jianshu.io/upload_images/2964446-6f92dac4cdd037e9.gif?imageMogr2/auto-orient/strip)

Demo地址:https://github.com/RaphetS/DemoRealm

一、Realm简介

数据库Realm,是用来替代sqlite的一种解决方案,它有一套自己的数据库存储引擎,比sqlite更轻量级,拥有更快的速度,并且具有很多现代数据库的特性,比如支持JSON,流式api,数据变更通知,自动数据同步,简单身份验证,访问控制,事件处理,最重要的是跨平台,目前已有Java,Objective C,Swift,React-Native,Xamarin这五种实现。

本篇文章用的版本为Realm 2.0.2(官方文档)

二、环境配置

(1) 在项目的build文件加上

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "io.realm:realm-gradle-plugin:2.0.2"
    }
}

(2) 在app的build文件加上

apply plugin: 'realm-android'

三、初始化Realm

(1) 在Application的oncreate()方法中Realm.init()

public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    Realm.init(this);
  }
}

(2)在Application的oncreate()方法中对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);
    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)在AndroidManifest.xml配置自定义的Application

<application
  android:name=".MyApplication"
  ...
/>

四、创建实体

(1)新建一个类继承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;
    }
}

多对多的关系:

public class Contact extends RealmObject {
    public String name;
    public RealmList<Email> emails;
}

public class Email extends RealmObject {
    public String address;
    public boolean active;
}

(2)其他相关说明

1、支持的数据类型:
boolean, byte, short, int, long, float, double, String, Date and byte[]
在Realm中byte, short, int, long最终都被映射成long类型

2、注解说明

@PrimaryKey
①字段必须是String、 integer、byte、short、 int、long 以及它们的封装类Byte, Short, Integer, and Long

②使用了该注解之后可以使用copyToRealmOrUpdate()方法,通过主键查询它的对象,如果查询到了,则更新它,否则新建一个对象来代替。

③使用了该注解将默认设置@index注解

④使用了该注解之后,创建和更新数据将会慢一点,查询数据会快一点。

@Required
数据不能为null

@Ignore
忽略,即该字段不被存储到本地

@Index
为这个字段添加一个搜索引擎,这将使插入数据变慢、数据增大,但是查询会变快。建议在需要优化读取性能的情况下使用。

五、增

(1)实现方法一:事务操作

类型一 :新建一个对象,并进行存储
Realm realm=Realm.getDefaultInstance();

realm.beginTransaction();
User user = realm.createObject(User.class); // Create a new object
user.setName("John");
user.setEmail("john@corporation.com");
realm.commitTransaction();
 类型二:复制一个对象到Realm数据库
Realm realm=Realm.getDefaultInstance();

User user = new User("John");
user.setEmail("john@corporation.com");

// Copy the object to Realm. Any further changes must happen on realmUser
realm.beginTransaction();
realm.copyToRealm(user);
realm.commitTransaction();

(2)实现方法二:使用事务块

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);
               
            }
        });
  • Gson gson = new GsonBuilder()

  • .setExclusionStrategies(new ExclusionStrategy() {

  • @Override

  • public boolean shouldSkipField(FieldAttributes f) {

  • return f.getDeclaringClass().equals(RealmObject.class);

  • }

  •  
  • @Override

  • public boolean shouldSkipClass(Class<?> clazz) {

  • return false;

  • }

  • })

  • .create();

  •  
  • // Configure Retrofit to use the proper GSON converter

  • RestAdapter restAdapter = new RestAdapter.Builder()

  • .setEndpoint("https://api.github.com")

  • .addConverterFactory(GsonConverterFactory.create(gson))

  • .build();

  •  
  • GitHubService service = restAdapter.create(GitHubService.class);

  •  

六、删

    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方法进行删除

七、改

Realm  mRealm=Realm.getDefaultInstance();

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

同样也可以用事物块来更新数据

八、查

(1)查询全部

查询结果为RealmResults<T>,可以使用mRealm.copyFromRealm(dogs)方法将它转为List<T>

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

(2)条件查询

 
  1. public void readRealmObject(String code){

  2. RealmResults<User> results = myOtherRealm.where(User.class)

  3. .equalTo("code", code)

  4. .findAll();

  5. StringBuilder stringBuilder = new StringBuilder();

  6. for (User c : results) {

  7. stringBuilder.append(c.getCode() + " , " + c.getName() + "\n");

  8. }

  9. }

常见的条件如下(详细资料请查官方文档):

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

  • equalTo() & notEqualTo()

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

  • isNull() & isNotNull()

  • isEmpty() & isNotEmpty()

(3)对查询结果进行排序

 /**
     * query (查询所有)
     */
    public List<Dog> queryAllDog() {
        RealmResults<Dog> dogs = mRealm.where(Dog.class).findAll();
        /**
         * 对查询结果,按Id进行排序,只能对查询结果进行排序
         */
        //增序排列
        dogs=dogs.sort("id");
        //降序排列
        dogs=dogs.sort("id", Sort.DESCENDING);
        return mRealm.copyFromRealm(dogs);
    }

(4)其他查询

sum,min,max,average只支持整型数据字段

 /**
     *  查询平均年龄
     */
    private void getAverageAge() {
         double avgAge=  mRealm.where(Dog.class).findAll().average("age");
    }

    /**
     *  查询总年龄
     */
    private void getSumAge() {
      Number sum=  mRealm.where(Dog.class).findAll().sum("age");
        int sumAge=sum.intValue();
    }

    /**
     *  查询最大年龄
     */
    private void getMaxId(){
      Number max=  mRealm.where(Dog.class).findAll().max("age");
        int maxAge=max.intValue();
    }

九、异步操作

大多数情况下,Realm的增删改查操作足够快,可以在UI线程中执行操作。但是如果遇到较复杂的增删改查,或增删改查操作的数据较多时,就可以子线程进行操作。

(1)异步增:

    private void addCat(final Cat cat) {
      RealmAsyncTask  addTask=  mRealm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                realm.copyToRealm(cat);
            }
        }, new Realm.Transaction.OnSuccess() {
            @Override
            public void onSuccess() {
                ToastUtil.showShortToast(mContext,"收藏成功");
            }
        }, new Realm.Transaction.OnError() {
            @Override
            public void onError(Throwable error) {
                ToastUtil.showShortToast(mContext,"收藏失败");
            }
        });

    }

最后在销毁Activity或Fragment时,要取消掉异步任务

@Override
    protected void onDestroy() {
        super.onDestroy();
       if (addTask!=null&&!addTask.isCancelled()){
            addTask.cancel();
        }
    }

(2)异步删

    private void deleteCat(final String id, final ImageView imageView){
      RealmAsyncTask  deleteTask=   mRealm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                Cat cat=realm.where(Cat.class).equalTo("id",id).findFirst();
                cat.deleteFromRealm();

            }
        }, new Realm.Transaction.OnSuccess() {
            @Override
            public void onSuccess() {
                ToastUtil.showShortToast(mContext,"取消收藏成功");
            }
        }, new Realm.Transaction.OnError() {
            @Override
            public void onError(Throwable error) {
                ToastUtil.showShortToast(mContext,"取消收藏失败");
            }
        });

    }

最后在销毁Activity或Fragment时,要取消掉异步任务

@Override
    protected void onDestroy() {
        super.onDestroy();
       if (deleteTask!=null&&!addTask.isCancelled()){
            deleteTask.cancel();
        }
    }

(3)异步改

RealmAsyncTask  updateTask=   mRealm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                Cat cat=realm.where(Cat.class).equalTo("id",mId).findFirst();
                cat.setName(name);
            }
        }, new Realm.Transaction.OnSuccess() {
            @Override
            public void onSuccess() {
                ToastUtil.showShortToast(UpdateCatActivity.this,"更新成功");
             
            }
        }, new Realm.Transaction.OnError() {
            @Override
            public void onError(Throwable error) {
                ToastUtil.showShortToast(UpdateCatActivity.this,"失败成功");
            }
        });

最后在销毁Activity或Fragment时,要取消掉异步任务

@Override
    protected void onDestroy() {
        super.onDestroy();
       if (updateTask!=null&&!addTask.isCancelled()){
            updateTask.cancel();
        }
    }

(4)异步查


     RealmResults<Cat>   cats=mRealm.where(Cat.class).findAllAsync();
        cats.addChangeListener(new RealmChangeListener<RealmResults<Cat>>() {
            @Override
            public void onChange(RealmResults<Cat> element) {
               element= element.sort("id");
                List<Cat> datas=mRealm.copyFromRealm(element);
              
            }
        });

最后在销毁Activity或Fragment时,要取消掉异步任务

 @Override
    protected void onDestroy() {
        super.onDestroy();
        cats.removeChangeListeners();
  
    }

十、数据迁移(版本升级)

方法一、删除旧版本的数据

RealmConfiguration config = new RealmConfiguration.Builder()
    .deleteRealmIfMigrationNeeded()
    .build()

方法二、设置schema 版本和 migration,对改变的数据进行处理

RealmConfiguration config = new RealmConfiguration.Builder()
    .schemaVersion(2) // Must be bumped when the schema changes
    .migration(new Migration()) // Migration to run instead of throwing an exception
    .build()

处理版本数据变化Migration

public class Migration implements RealmMigration {

    @Override
    public void migrate(final DynamicRealm realm, long oldVersion, long newVersion) {
        // During a migration, a DynamicRealm is exposed. A DynamicRealm is an untyped variant of a normal Realm, but
        // with the same object creation and query capabilities.
        // A DynamicRealm uses Strings instead of Class references because the Classes might not even exist or have been
        // renamed.

        // Access the Realm schema in order to create, modify or delete classes and their fields.
        RealmSchema schema = realm.getSchema();

        /************************************************
            // Version 0
            class Person
                @Required
                String firstName;
                @Required
                String lastName;
                int    age;
            // Version 1
            class Person
                @Required
                String fullName;            // combine firstName and lastName into single field.
                int age;
        ************************************************/
        // Migrate from version 0 to version 1
        if (oldVersion == 0) {
            RealmObjectSchema personSchema = schema.get("Person");

            // Combine 'firstName' and 'lastName' in a new field called 'fullName'
            personSchema
                    .addField("fullName", String.class, FieldAttribute.REQUIRED)
                    .transform(new RealmObjectSchema.Function() {
                        @Override
                        public void apply(DynamicRealmObject obj) {
                            obj.set("fullName", obj.getString("firstName") + " " + obj.getString("lastName"));
                        }
                    })
                    .removeField("firstName")
                    .removeField("lastName");
            oldVersion++;
        }

        /************************************************
            // Version 2
                class Pet                   // add a new model class
                    @Required
                    String name;
                    @Required
                    String type;
                class Person
                    @Required
                    String fullName;
                    int age;
                    RealmList<Pet> pets;    // add an array property
         ************************************************/
        // Migrate from version 1 to version 2
        if (oldVersion == 1) {

            // Create a new class
            RealmObjectSchema petSchema = schema.create("Pet")
                    .addField("name", String.class, FieldAttribute.REQUIRED)
                    .addField("type", String.class, FieldAttribute.REQUIRED);

            // Add a new field to an old class and populate it with initial data
            schema.get("Person")
                .addRealmListField("pets", petSchema)
                .transform(new RealmObjectSchema.Function() {
                    @Override
                    public void apply(DynamicRealmObject obj) {
                        if (obj.getString("fullName").equals("JP McDonald")) {
                            DynamicRealmObject pet = realm.createObject("Pet");
                            pet.setString("name", "Jimbo");
                            pet.setString("type", "dog");
                            obj.getList("pets").add(pet);
                        }
                    }
                });
            oldVersion++;
        }

        /************************************************
            // Version 3
                class Pet
                    @Required
                    String name;
                    int type;               // type becomes int
                class Person
                    String fullName;        // fullName is nullable now
                    RealmList<Pet> pets;    // age and pets re-ordered (no action needed)
                    int age;
         ************************************************/
        // Migrate from version 2 to version 3
        if (oldVersion == 2) {
            RealmObjectSchema personSchema = schema.get("Person");
            personSchema.setNullable("fullName", true); // fullName is nullable now.

            // Change type from String to int
            schema.get("Pet")
                .addField("type_tmp", int.class)
                .transform(new RealmObjectSchema.Function() {
                    @Override
                    public void apply(DynamicRealmObject obj) {
                        String oldType = obj.getString("type");
                        if (oldType.equals("dog")) {
                            obj.setLong("type_tmp", 1);
                        } else if (oldType.equals("cat")) {
                            obj.setInt("type_tmp", 2);
                        } else if (oldType.equals("hamster")) {
                            obj.setInt("type_tmp", 3);
                        }
                    }
                })
                .removeField("type")
                .renameField("type_tmp", "type");
            oldVersion++;
        }
    }
}




转载链接:https://www.jianshu.com/p/28912c2f31db
https://github.com/RaphetS/DemoRealm/blob/master/app/src/main/java/org/raphets/demorealm/util/RealmHelper.java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路途…

点滴记录

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值