1. 程式人生 > >Android Realm資料庫的查詢及自動更新

Android Realm資料庫的查詢及自動更新

上一篇文章Android Realm資料庫的使用寫了Relam資料庫的基本配置和基本用法,這次主要看看Realm資料庫的查詢以及自動更新。

1.查詢

查詢分為同步和非同步,同步和非同步的使用請看上一篇文章,這次主要是學習查詢條件的使用:

//查詢年齡在10~50歲的Student,並且結果按降序排列
 RealmResults<Student> list = mRealm.where(Student.class)
        .between("age", 10, 50)
        .findAllSorted("age", Sort.DESCENDING);

 //查詢年齡大於等於70或者名字叫"斯巴達1"的所有Student,結果按升序排列
RealmResults<Student> list = mRealm.where(Student.class) .beginGroup() .greaterThanOrEqualTo("age", 70) .or() .equalTo("name", "斯巴達1") .endGroup() .findAllSorted("age", Sort.ASCENDING); //查詢班級是1並且年齡是20的Student RealmResults<Student> list = mRealm.where(Student.class) .equalTo("clazz"
, 1) .findAll() .where() .equalTo("age", 20) .findAll();

基本語法和GreenDao差不多,用過類似ORM的應該都很容易上手。

2.自動更新

如果Realm的例項存在於帶有Looper,也就是UI執行緒,那麼這個Realm就擁有自動更新的功能。也就是說如果Realm資料庫發生了變化,那麼資料庫就會在下一個事件迴圈中自動更新,這樣也就實現了資料與UI的同步。

如果你在子執行緒中新增資料到Realm資料庫,你可以新增一個onChangeListener來監聽資料的變化,這樣在資料發生變化的時候就會執行相應的操作。

public class MyActivity extends Activity {
    private Realm realm;
    private RealmChangeListener realmListener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      realm = Realm.getDefaultInstance();
      realmListener = new RealmChangeListener() {
        @Override
        public void onChange(Realm realm) {
            // ... do something with the updates (UI, etc.) ...
        }};
      realm.addChangeListener(realmListener);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // Remove the listener.
        realm.removeChangeListener(realmListener);
        //or use realm.removeAllChangeListeners() if needed.
        // Close the Realm instance.
        realm.close();
    }
}

這些變化的監聽也可以新增在RealmObject或者RealmResults的例項中,你可以通過這樣的方式來監視物件和查詢結果的改變。另外,當監聽回撥函式被呼叫時,相應的資料已經被更新,不需要去做重新整理操作。

public class MyActivity extends Activity {
    private Realm realm;
    private RealmChangeListener puppiesListener;
    private RealmChangeListener dogListener;

    private RealmResults<Dog> puppies;
    private Dog dog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      realm = Realm.getDefaultInstance();
      puppiesListener = new RealmChangeListener() {
        @Override
        public void onChange(RealmResults<Dog> puppies) {
            // ... do something with the updated puppies instance
        }};

      // Find all the puppies
      puppies = realm.where(Dog.class).lessThanOrEqualTo("age", 2).findAll();
      puppies.addChangeListener(puppiesListener);

      dogListener = new RealmChangeListener() {
        @Override
        public void onChange(Dog dog) {
            // ... do something with the updated Dog instance
        }};

      dog = realm.where(Dog.class).equalTo("name", "Fido").findFirst();
      dog.addChangeListener(dogListener);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // Remove the listeners
        puppies.removeChangeListener(puppiesListener);
        dog.removeChangeListener(dogListener);
        // Close the Realm instance.
        realm.close();
    }
}

如果Realm例項存在與非UI執行緒,那麼資料不會發生自動重新整理,知道手動呼叫waitForChange()方法。如果您想確定當前 Realm 例項是否有自動更新功能,可以通過呼叫 isAutoRefresh() 方法查詢。官方是這樣說的:

Change listeners only work on Looper threads. For non-looper threads, you manually have to use Realm.waitForChange() instead.
也就是說對Realm資料變化的監聽只會在主執行緒執行,要想在非UI執行緒使用,需要使用waitForChange()代替。

另外,官方還重寫了ListView和RecyclerView的Adapter,可以實現資料的實時重新整理。用法大同小異,需要在module一級的build.gradle中新增依賴:

compile 'io.realm:android-adapters:1.4.0'

具體用法以RecyclerView為例:

public class DetailActivity extends AppCompatActivity {

  public static final String STUDENT = "STUDENT";
  private Realm mRealm;

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_detail);
    getSupportActionBar().setTitle("RealmAdapter");
    mRealm = Realm.getDefaultInstance();

    RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.mRecyclerView);
    mRecyclerView.setHasFixedSize(true);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    //Realm的查詢方法

    //查詢年齡在10~50歲的Student,並且結果按降序排列
    RealmResults<Student> list = mRealm.where(Student.class)
        .between("age", 10, 50)
        .findAllSorted("age", Sort.DESCENDING);
    mRecyclerView.setAdapter(new MyAdapter(this, list, true));//這裡就設定了自動更新
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.insert) {
      mRealm.beginTransaction();
      List<Student> list = new ArrayList<>();
      for (int i = 0; i < 100; i++) {
        Student s = new Student(UUID.randomUUID().toString(), "斯巴達" + i, i, (i % 2) + 1);
        list.add(s);
      }
      mRealm.copyToRealm(list);
      mRealm.commitTransaction();
    }
    return super.onOptionsItemSelected(item);
  }

  class MyAdapter extends RealmRecyclerViewAdapter<Student, MyAdapter.ViewHolder> {

    public MyAdapter(@NonNull Context context, @Nullable OrderedRealmCollection<Student> data, boolean autoUpdate) {
      super(context, data, autoUpdate);
    }

    class ViewHolder extends RecyclerView.ViewHolder {
      private TextView name;
      private TextView clazz;

      public ViewHolder(View itemView) {
        super(itemView);
        name = (TextView) itemView.findViewById(R.id.name);
        clazz = (TextView) itemView.findViewById(R.id.clazz);
      }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
      View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);
      return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
      Student student = getData().get(position);
      holder.name.setText(student.getName());
      holder.clazz.setText(String.format(Locale.CHINA, "%d班", student.getClazz()));
    }
  }


  @Override
  protected void onDestroy() {
    super.onDestroy();
    if (mRealm != null && !mRealm.isClosed()) {
      mRealm.close();
      mRealm = null;
    }
  }
}

想了解更詳細的內容可以看官方介紹