寫在前面:html
又到一年一度七夕虐狗節,看着你們忍受着各類朋友圈和QQ空間還有現實生活中的輪番轟炸,我實在不忍心再在這裏給你們補刀,因此我以爲今天不虐狗,繼續給你們分享有用的。java
若是你比較關心android開發的最新動態的話,我想你必定知道android數據庫新王者,沒錯,就是這個東西——Realm。android
在安卓開發中,咱們有sharedPreference和文件操做,固然還有一直爲之自豪的輕量級數據庫sqlite。git
SharedPreference實際上是採用xml的方式,以鍵值對形式存儲基本數據類型的數據,對於複雜的數據篩選查詢操做,file和sharedpreference就顯得雞肋,這個時候sqlite即可以知足有大量複雜查詢要求的緩存數據操做,可是它的使用一直被人詬病,是的,由於代碼量太多了!github
做爲一個要爲全世界作貢獻的程序猿,怎麼能夠忍受這樣多的代碼實現一點小東西呢?No,No,咱們絕對不能接受!!!sql
還好網上出現了不少優秀的ORM框架供咱們參略,好比ORMite,greenDao等,而這些都是基於SQLite的。數據庫
額,仍是不扯遠了,直接給你們帶來今天的主角,沒錯,就是它——realm!緩存
對於初學Realm的小夥伴,確定仍是應該對比着咱們熟悉不過的sqlite來講的。網絡
相比sqlite,Realm具備別人不可比擬的神奇速度,哦,這不是重點,它還有強大先進的特性等着你,好比數據加密支持,對Json的支持,流暢的API,數據觀察者變化,全部的一切都是爲了讓咱們程序猿更加瀟灑!什麼?程序猿還能夠瀟灑??有的小夥伴確定怒火中燒了?樓主別裝逗比。app
額,好吧,只要你心瀟灑,你人就瀟灑啦~怎麼跑題了呢?仍是迴歸正題!!!
哦,對了,對於Realm,有一個很是強大的東西,就是它能夠和當前最主流的網絡框架Retrofit以及強大的異步框架Rxjava聯用哦,對於Retrofit的介紹能夠去直通車:
http://www.cnblogs.com/liushilin/p/5680135.html
等等,怎麼總感受少說了點什麼,額,對,如標題同樣,它還有一個很強大的特性,那就是它能夠總能獲取到最新的數據,是的,它是一個live db~~
額,仍是說說怎麼使用吧,更具體的能夠看官方API頻道:https://realm.io/docs/java/latest/
1)首先在你的project的gradle文件中添加這樣一句,注意:是工程gradle,不是app的gradle,沒法編譯別怪樓主沒提醒你哈!!
1 classpath 'io.realm:realm-gradle-plugin:1.1.0'
2)而後再去app下的gradle頭部添加:
1 apply plugin: 'realm-android'
3)隨便寫一個Java實體類,例如我寫了一個用戶類User,只須要繼承RealmObject便可,對於主鍵能夠添加註解@PrimaryKey,對於@Required天然是必填項,@Ignore便是可忽略的。
1 package com.example.nanchen.realmdemo; 2 3 import io.realm.RealmObject; 4 import io.realm.annotations.Ignore; 5 import io.realm.annotations.PrimaryKey; 6 import io.realm.annotations.Required; 7 8 /** 9 * 10 * @author nanchen 11 * @date 2016-08-08 17:21:15 12 */ 13 public class User extends RealmObject { 14 //主鍵必須添加註解 15 @PrimaryKey 16 private int id;//主鍵id 17 @Required //註解設爲Required表明必須項 18 private String name;//姓名 19 20 private int age;//年齡 21 22 @Ignore //表示忽視項,數據庫不會存儲該字段 23 private boolean hasGrilFriend;//是否有女友 24 25 public User() { 26 } 27 28 public User(int id, String name, int age) { 29 this.id = id; 30 this.name = name; 31 this.age = age; 32 } 33 34 public User(String name, int id, int age, boolean hasGrilFriend) { 35 this.name = name; 36 this.id = id; 37 this.age = age; 38 this.hasGrilFriend = hasGrilFriend; 39 } 40 41 public boolean isHasGrilFriend() { 42 return hasGrilFriend; 43 } 44 45 public void setHasGrilFriend(boolean hasGrilFriend) { 46 this.hasGrilFriend = hasGrilFriend; 47 } 48 49 public int getId() { 50 return id; 51 } 52 53 public void setId(int id) { 54 this.id = id; 55 } 56 57 public String getName() { 58 return name; 59 } 60 61 public void setName(String name) { 62 this.name = name; 63 } 64 65 public int getAge() { 66 return age; 67 } 68 69 public void setAge(int age) { 70 this.age = age; 71 } 72 73 @Override 74 public String toString() { 75 return "User{" + 76 "id=" + id + 77 ", name='" + name + '\'' + 78 ", age=" + age + 79 ", hasGrilFriend=" + hasGrilFriend + 80 '}'; 81 } 82 }
4)額,這個東西確定也是須要初始化的嘛。額,樓主這裏就單獨寫一個RealmUtils工具類了。
1 package com.example.nanchen.realmdemo; 2 3 import android.content.Context; 4 5 import io.realm.Realm; 6 import io.realm.RealmConfiguration; 7 8 /** 9 * @author nanchen 10 * @date 16-8-8 下午5:51 11 */ 12 public class RealmUtils { 13 private Context context; 14 private static RealmUtils mInstance; 15 private String realName = "myRealm.realm"; 16 17 private RealmUtils(Context context){ 18 this.context = context; 19 } 20 21 public static RealmUtils getInstance(Context context){ 22 if (mInstance == null){ 23 synchronized (RealmUtils.class){ 24 if (mInstance == null){ 25 mInstance = new RealmUtils(context); 26 } 27 } 28 } 29 return mInstance; 30 } 31 32 /** 33 * 得到Realm對象 34 * @return 35 */ 36 public Realm getRealm(){ 37 return Realm.getInstance(new RealmConfiguration.Builder(context).name(realName).build()); 38 } 39 }
5)而後在看看基本操做,樓主這裏就使用比較流行的Dao模式吧
先寫一個Dao接口,註釋很清楚哈。
1 package com.example.nanchen.realmdemo; 2 3 import java.sql.SQLException; 4 import java.util.List; 5 6 /** 7 * 操做數據庫的接口Dao 8 * 9 * @author nanchen 10 * @date 2016-08-08 17:23:18 11 * 12 */ 13 public interface UserDao { 14 15 /** 16 * 插入一個用戶 17 * @param user 須要插入的用戶對象 18 * @throws SQLException 19 */ 20 void insert(User user) throws SQLException; 21 22 /** 23 * 得到全部的用戶列表 24 * @return 用戶列表 25 * @throws SQLException 26 */ 27 List<User> getAllUser() throws SQLException; 28 29 /** 30 * 更新一個用戶 31 * @param user 須要更新的用戶類 32 * @return 更新後的對象 33 * @throws SQLException 34 */ 35 User updateUser(User user) throws SQLException; 36 37 /** 38 * 根據姓名修改新姓名 39 * @param name1 老名字 40 * @param name2 新名字 41 * @throws SQLException 42 */ 43 void updateUser(String name1,String name2) throws SQLException; 44 45 /** 46 * 根據id刪除用戶 47 * @param id 用戶主鍵 48 * @throws SQLException 49 */ 50 void deleteUser(int id) throws SQLException; 51 52 /** 53 * 異步添加用戶 54 * @param user 須要添加的用戶對象 55 * @throws SQLException 56 */ 57 void insertUserAsync(User user) throws SQLException; 58 59 /** 60 * 按名字或者年齡查找第一個User 61 */ 62 User findByNameOrAge(String name1,int age1) throws SQLException; 63 64 /** 65 * 清楚全部 66 * @throws SQLException 67 */ 68 void deleteAll() throws SQLException; 69 70 /** 71 * 關閉事務 72 */ 73 void closeRealm(); 74 }
而後是咱們的Dao實現類,一樣是滿滿的註釋,看樓主對大家這麼用心,很感動有木有,想以身相許了有木有,額,樓主,不搞基!!!
不過你既然這麼心存感激,就在文章右下角給樓主點個贊吧~~嘿嘿。
1 package com.example.nanchen.realmdemo; 2 3 import android.content.Context; 4 5 import java.sql.SQLException; 6 import java.util.List; 7 8 import io.realm.Realm; 9 import io.realm.Realm.Transaction; 10 import io.realm.RealmResults; 11 import io.realm.Sort; 12 13 /** 14 * @author nanchen 15 * @date 16-8-8 下午5:49 16 */ 17 public class UserDaoImpl implements UserDao { 18 19 private Context context; 20 private Realm mRealm; 21 22 public UserDaoImpl(Context context) { 23 mRealm = RealmUtils.getInstance(context).getRealm(); 24 } 25 26 /** 27 * 同步插入 28 * @param user 須要插入的用戶對象 29 * @throws SQLException 30 */ 31 @Override 32 public void insert(User user) throws SQLException { 33 mRealm.beginTransaction();//必須先開啓事務 34 User user1 = mRealm.copyToRealm(user);//把User對象複製到Realm 35 mRealm.commitTransaction();//提交事務 36 // mRealm.close();//必須關閉,否則會形成內存泄漏 37 } 38 39 /** 40 * 返回全部的User對象,並按照名字首字母排序 41 * @return User對象表 42 * @throws SQLException 43 */ 44 @Override 45 public List<User> getAllUser() throws SQLException { 46 List<User> list = null; 47 RealmResults<User> results = mRealm.where(User.class).findAll(); 48 results.sort("name", Sort.DESCENDING);//針對字符串的排序,但目前並非支持全部字符集 49 list = results; 50 // mRealm.close(); 51 return list; 52 } 53 54 /** 55 * 更新一個User 56 * @param user 須要更新的用戶類 57 * @return 返回更新後的User 58 * @throws SQLException 59 */ 60 @Override 61 public User updateUser(User user) throws SQLException { 62 mRealm.beginTransaction();//開啓事務 63 User user1 = mRealm.copyToRealmOrUpdate(user); 64 mRealm.commitTransaction();//提交事務 65 // mRealm.close();//必須關閉事務 66 return user1; 67 } 68 69 /** 70 * @param name1 老名字 71 * @param name2 新名字 72 * @throws SQLException 73 */ 74 @Override 75 public void updateUser(String name1, String name2) throws SQLException { 76 mRealm.beginTransaction();//開啓事務 77 mRealm.where(User.class) 78 .equalTo("name",name1)//查詢出name爲name1的User對象 79 .findFirst() 80 .setName(name2);//修改查詢出的第一個對象的名字 81 mRealm.commitTransaction(); 82 // mRealm.close(); 83 } 84 85 /** 86 * 根據id刪除一個User 87 * @param id 用戶主鍵 88 * @throws SQLException 89 */ 90 @Override 91 public void deleteUser(int id) throws SQLException { 92 User user = mRealm.where(User.class).equalTo("id",id).findFirst();//刪除id列值爲id的行 93 mRealm.beginTransaction(); 94 user.deleteFromRealm();//從數據庫刪除 95 mRealm.commitTransaction(); 96 // mRealm.close(); 97 } 98 99 /** 100 * 異步插入User 101 * @param user 須要添加的用戶對象 102 * @throws SQLException 103 */ 104 @Override 105 public void insertUserAsync(final User user) throws SQLException { 106 //一個Realm只能在同一個線程訪問,在子線程中進行數據庫操做必須從新獲取realm對象 107 mRealm.executeTransaction(new Transaction() { 108 @Override 109 public void execute(Realm realm) { 110 realm.beginTransaction();//開啓事務 111 User user1 = realm.copyToRealm(user); 112 realm.commitTransaction(); 113 realm.close();//記得關閉事務 114 } 115 }); 116 // mRealm.close();//外面也不能忘記關閉事務 117 } 118 119 120 /** 121 * 返回第一個指定名字或者年齡的對象 122 * @param name1 名字 123 * @param age1 年齡 124 */ 125 @Override 126 public User findByNameOrAge(String name1,int age1) throws SQLException{ 127 User user = mRealm.where(User.class) 128 .equalTo("name",name1)//至關於where name = name1 129 .or()//或,鏈接查詢條件,沒有這個方式時會默認是&鏈接 130 .equalTo("age",age1)//至關於where age = age1 131 .findFirst(); 132 //總體至關於select * from (表名) where name = (傳入的name) or age = (傳入的age)limit 1; 133 // mRealm.close(); 134 return user; 135 } 136 137 @Override 138 public void deleteAll() throws SQLException { 139 mRealm.beginTransaction(); 140 mRealm.where(User.class).findAll().deleteAllFromRealm(); 141 mRealm.commitTransaction(); 142 // mRealm.close(); 143 } 144 145 146 @Override 147 public void closeRealm() { 148 mRealm.close(); 149 } 150 }
6)實際上不少時候咱們的close都是寫在方法裏面的,樓主只是爲了測試Demo的好用,就單獨寫了一個關閉事務的方法來標新立異了哈,你們各自創新~~
額,對了,close你是必須必須調用的,否則你會內存泄漏!!
再簡單看一下樓主的調用:
1 package com.example.nanchen.realmdemo; 2 3 import android.support.v7.app.AppCompatActivity; 4 import android.os.Bundle; 5 import android.util.Log; 6 7 import java.sql.SQLException; 8 9 public class MainActivity extends AppCompatActivity { 10 private UserDao userDao; 11 12 @Override 13 protected void onCreate(Bundle savedInstanceState) { 14 super.onCreate(savedInstanceState); 15 setContentView(R.layout.activity_main); 16 17 userDao = new UserDaoImpl(this); 18 try { 19 userDao.deleteAll();//先刪除全部,以避免demo出現主鍵已經存在的異常 20 User user = new User(); 21 user.setId(10); 22 user.setName("小刺蝟"); 23 user.setAge(22); 24 user.setHasGrilFriend(true); 25 userDao.insert(user); 26 27 Log.d("flag","插入小刺蝟----"+userDao.getAllUser().toString()); 28 29 for (int i = 0; i < 5; i++) { 30 userDao.insert(new User(i,"南塵"+i,20+i)); 31 } 32 Log.d("flag","插入5個對象----"+userDao.getAllUser().toString()); 33 Log.d("flag","查詢1----"+userDao.findByNameOrAge("南塵1",20)); 34 Log.d("flag","查詢2----"+userDao.findByNameOrAge("南塵1",23)); 35 userDao.updateUser("南塵1","nanchen"); 36 Log.d("flag","更新1----"+userDao.findByNameOrAge("南塵1",23)); 37 userDao.deleteUser(0);//刪除0 38 Log.d("flag","刪除後查看----"+userDao.getAllUser().toString()); 39 40 41 //統一關閉事務 42 userDao.closeRealm(); 43 } catch (SQLException e) { 44 e.printStackTrace(); 45 } 46 } 47 }
7)運行查看結果,好像沒啥問題呢。
哈哈,對於Realm的簡單使用今天就講到這裏哦,你們趕忙搞定一波學習,有女友的陪女友去,沒女友的,趕忙學會了好找女友!
項目已同步至:https://github.com/nanchen2251/RealmDemo
額,最後根據Realm類總結一番:
1)Realm類能夠對你的持久化對象進行存儲和事務管理,能夠用來建立RealmObjects實例,而且領域內的對象能夠在任什麼時候候查詢和讀取。
2)修改,插入和刪除操做均必須在一個完整的事務中,在更新操做中,咱們能夠經過copyToRealmOrUpdate來作,可是官方更推薦咱們用先查詢出來後更新的方法,上面代碼也有提到。
3)該事務確保多個實例(在多個線程中)能夠在一個一致的狀態和保證事務在ACID前提下,訪問相同的對象。
4)當一個Realm實例操做完成後,必定必定要記住調用close()方法,不然致使了本地資源沒法釋放而引發了OOM別怪樓主沒提醒。
5)Realm實例不能不在不一樣的線程間訪問操做,因此樓主的異步插入裏面打開了一個新的實例,固然也得關掉它!
6)對於UI線程來講。打開和關閉Realm實例,應當放在onCreate/onDestory或者onPause/onStop方法中。
7)在不一樣的線程間,Realm實例使用Handler機制來調整它的狀態。也就是說,Realm實例在線程中,若是沒有Looper,是不能收到更新通知的。除非手動調用waitForChange方法。
8)重點注意:Realm數據庫的主鍵字段不是自動增加的,而且不支持設置數據的自增。須要本身設置,作添加的時候若是不給id字段值,默認爲是0。後面再添加的話會報錯說id爲0的字段已經存在。尤爲是批量添加的時候要注意,小心出現只添加了一條記錄的悲劇!
9)數據自動更新。能夠經過調用addChangeListener(context)來作。當數據庫的數據有變化時,系統會自動回調此方法,說到這裏,小夥伴是否是心動了?在列表數據的時候,麻麻不再用擔憂我忘了更新數據庫了。
注:此文章爲原創,歡迎轉載,請在文章頁面明顯位置給出此文連接:http://www.cnblogs.com/liushilin/p/5752099.html若您以爲這篇文章還不錯請點擊下右下角的推薦,很是感謝!