GreenDAO和Realm使用

概述

最近打算研究一下Android的ORM框架据忘,即對(duì)象關(guān)系數(shù)據(jù)映射搞糕,ORM框架能很好的幫我們簡(jiǎn)化數(shù)據(jù)庫(kù)操作邏輯窍仰,增加開發(fā)效率,而且好的ORM還能幫我們?cè)黾訄?zhí)行效率针史。世面上有很多ORM框架碟狞,比如OrmLite、SugarORM频祝、GreenDAO竭业、ActiveAndroid、realm等,搜了一些資料進(jìn)行對(duì)比锯玛,感覺GreenDAO和Realm這兩款還是比較優(yōu)秀的,所以這里先介紹下GreenDAO和Realm的簡(jiǎn)單使用拙友。

GreenDAO

GreenDAO是基于Android原生數(shù)據(jù)庫(kù)框架進(jìn)行封裝的遗契,使我們不用寫復(fù)雜的SQL語句及很多的重復(fù)性語句。GreenDAO對(duì)Android進(jìn)行了高度優(yōu)化漾根,具有輕量級(jí)鲫竞、高性能、支持加密寄疏、支持protobuf僵井、對(duì)象激活批什、代碼自動(dòng)生成等特點(diǎn)。

  • 配置依賴
    引入GreenDAO需要分別在工程的build.gradle和Module的build.gradle進(jìn)行配置朋蔫。

工程的build.gradle:

buildscript {
    repositories {
        jcenter()
        mavenCentral() // 添加這個(gè)倉(cāng)庫(kù)
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.1'
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // 添加插件路徑
    }
}

Module的build.gradle:

apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // 添加插件的調(diào)用
 
dependencies {
    implementation 'org.greenrobot:greendao:3.2.2' // 添加庫(kù)的依賴
}
  • 配置數(shù)據(jù)庫(kù)版本號(hào)和代碼生成路徑
    GreenDAO可以管理數(shù)據(jù)庫(kù)版本驯妄、自動(dòng)生成代碼合砂,需要我們通過配置告訴它數(shù)據(jù)庫(kù)版本號(hào)以及生成代碼的路徑翩伪,配置寫在Module的build.gradle,如下:
greendao {
    schemaVersion 6                       //數(shù)據(jù)庫(kù)版本號(hào)
    targetGenDir "src/main/java"     //生成代碼的根路徑
    daoPackage "com.example.lenovo.dao"          //在根路徑下生成類的包名
}
  • 編寫Entity類
    GreedDAO會(huì)根據(jù)注解自動(dòng)生成代碼凛剥,所以開始只需要編寫實(shí)體類即可轻姿,GreenDAO會(huì)幫我們自動(dòng)生成創(chuàng)建數(shù)據(jù)庫(kù)的代碼及各個(gè)表對(duì)應(yīng)的dao類逻炊。如下是一個(gè)Entity類:
@Entity
public class Student {
    @Id(autoincrement = true) Long id;
    String name;
    int age;
    String grades;
    @ToMany(referencedJoinProperty = "studentId")
    List<Course> courseList;
}

這就是個(gè)簡(jiǎn)單的數(shù)據(jù)類余素,只是增加了幾個(gè)注解炊昆,然后編譯一下工程凤巨,神奇的事情就會(huì)發(fā)生,這個(gè)類會(huì)擴(kuò)張成一個(gè)比較復(fù)雜的類炊林,其中Course是另一個(gè)類似的實(shí)體類,這里不再貼出代碼了。擴(kuò)張后的Student類如下:

@Entity
public class Student {
    @Id(autoincrement = true) Long id;
    String name;
    int age;
    String grades;
    @ToMany(referencedJoinProperty = "studentId")
    List<Course> courseList;
    /** Used to resolve relations */
    @Generated(hash = 2040040024)
    private transient DaoSession daoSession;
    /** Used for active entity operations. */
    @Generated(hash = 1943931642)
    private transient StudentDao myDao;
    @Generated(hash = 990890750)
    public Student(Long id, String name, int age, String grades) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.grades = grades;
    }
    @Generated(hash = 1556870573)
    public Student() {
    }
    public Long getId() {
        return this.id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return this.age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getGrades() {
        return this.grades;
    }
    public void setGrades(String grades) {
        this.grades = grades;
    }
    /**
     * To-many relationship, resolved on first access (and after reset).
     * Changes to to-many relations are not persisted, make changes to the target entity.
     */
    @Generated(hash = 838351874)
    public List<Course> getCourseList() {
        if (courseList == null) {
            final DaoSession daoSession = this.daoSession;
            if (daoSession == null) {
                throw new DaoException("Entity is detached from DAO context");
            }
            CourseDao targetDao = daoSession.getCourseDao();
            List<Course> courseListNew = targetDao._queryStudent_CourseList(id);
            synchronized (this) {
                if (courseList == null) {
                    courseList = courseListNew;
                }
            }
        }
        return courseList;
    }
    /** Resets a to-many relationship, making the next get call to query for a fresh result. */
    @Generated(hash = 829241409)
    public synchronized void resetCourseList() {
        courseList = null;
    }
    /**
     * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
     * Entity must attached to an entity context.
     */
    @Generated(hash = 128553479)
    public void delete() {
        if (myDao == null) {
            throw new DaoException("Entity is detached from DAO context");
        }
        myDao.delete(this);
    }
    /**
     * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
     * Entity must attached to an entity context.
     */
    @Generated(hash = 1942392019)
    public void refresh() {
        if (myDao == null) {
            throw new DaoException("Entity is detached from DAO context");
        }
        myDao.refresh(this);
    }
    /**
     * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
     * Entity must attached to an entity context.
     */
    @Generated(hash = 713229351)
    public void update() {
        if (myDao == null) {
            throw new DaoException("Entity is detached from DAO context");
        }
        myDao.update(this);
    }
    /** called by internal mechanisms, do not call yourself. */
    @Generated(hash = 1701634981)
    public void __setDaoSession(DaoSession daoSession) {
        this.daoSession = daoSession;
        myDao = daoSession != null ? daoSession.getStudentDao() : null;
    }
    
}

可以看到自動(dòng)生成了很多代碼,包括構(gòu)造函數(shù)、get隘道、set郎笆、增刪改查方法等宛蚓。這些代碼就是GreenDAO根據(jù)我們寫的那幾個(gè)注解生成的。
@Entity表示這個(gè)類會(huì)生成一個(gè)對(duì)應(yīng)的表远舅,這個(gè)注解還有一些屬性可以設(shè)置:

@Entity(
        schema = "schemaName",    //表示實(shí)體類對(duì)應(yīng)的表
        active = true,                         //表示實(shí)體類是“活的”痕钢,具有增刪改查
        nameInDb = "AWESOME_USERS",   //數(shù)據(jù)庫(kù)中使用的別名
        indexes = {                                             //定義索引
                @Index(value = "name DESC", unique = true)
        },
        createInDb = true,                 //是否生成表蚤吹,默認(rèn)true
        generateConstructors = true,    //是否生成構(gòu)造方法
        generateGettersSetters = true  //是否生成get距辆、set方法
)

@Id(autoincrement = true) 表示表的主鍵暮刃,并且自動(dòng)增加
@ToMany(referencedJoinProperty = "studentId") 表示一個(gè)一對(duì)多的關(guān)系椭懊,并通過studentId關(guān)聯(lián)。
這類注解還有很多氧猬,比如
@Property(nameInDb="name") 可以配置一個(gè)非字段名的列盅抚,不配置默認(rèn)使用字段名
@NotNull 表示這列不能為空
@Transient 標(biāo)記的字段不會(huì)生成表的一列
@Unique 表示這列只能有唯一值
@ToOne 表示一對(duì)一關(guān)系 ,如@ToOne(joinProperty = "name")
@OrderBy 表示這列如何排序柱锹,當(dāng)get這列數(shù)據(jù)的時(shí)候會(huì)按照這個(gè)排序給出

再看一下之前配置的路徑src/main/java之下的com.example.lenovo.dao包下丰包,也生成了幾個(gè)類:



這個(gè)幾個(gè)類就是我們會(huì)用到的數(shù)據(jù)庫(kù)操作類邑彪。
其中的DaoMaster類有兩個(gè)內(nèi)部類寄症,OpenHelper和DevOpenHelper,如下


    /**
     * Calls {@link #createAllTables(Database, boolean)} in {@link #onCreate(Database)} -
     */
    public static abstract class OpenHelper extends DatabaseOpenHelper {
        public OpenHelper(Context context, String name) {
            super(context, name, SCHEMA_VERSION);
        }

        public OpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory, SCHEMA_VERSION);
        }

        @Override
        public void onCreate(Database db) {
            Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
            createAllTables(db, false);
        }
    }

    /** WARNING: Drops all table on Upgrade! Use only during development. */
    public static class DevOpenHelper extends OpenHelper {
        public DevOpenHelper(Context context, String name) {
            super(context, name);
        }

        public DevOpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory);
        }

        @Override
        public void onUpgrade(Database db, int oldVersion, int newVersion) {
            Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
            dropAllTables(db, true);
            onCreate(db);
        }
    }

后者是前者子類释漆,在OpenHelper的onCreate方法中進(jìn)行了數(shù)據(jù)庫(kù)創(chuàng)建灵汪,而DevOpenHelper的onUpdate方法中是刪除數(shù)據(jù)庫(kù)并重新創(chuàng)建柑潦,每次升級(jí)數(shù)據(jù)庫(kù)就會(huì)調(diào)用這個(gè)方法,所以實(shí)際開發(fā)中我們可以自己實(shí)現(xiàn)一個(gè)OpenHelper览露,并在onUpdate方法中處理數(shù)據(jù)庫(kù)升級(jí)差牛。

  • 初始化
    有了上面生成的幾個(gè)類后,就可以進(jìn)行初始化工作了偏化,一般是在Application的onCreate方法中進(jìn)行侦讨,如下代碼:
public class MyApplication extends Application {
    private DaoSession daoSession;
    @Override
    public void onCreate() {
        super.onCreate();
        DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(this, "test.db");
        SQLiteDatabase database = devOpenHelper.getWritableDatabase();
        DaoMaster daoMaster = new DaoMaster(database);
        daoSession = daoMaster.newSession();
    }

    public DaoSession getDaoSession(){
        return daoSession;
    }
}

這里通過OpenHelper生成了一個(gè)名為test的數(shù)據(jù)庫(kù)韵卤,并最終通過DaoMaster獲得了一個(gè)DaoSession保存在了Application中。

  • 增刪改查
    我們對(duì)數(shù)據(jù)表的操作都是通過對(duì)應(yīng)的dao類需忿,dao類可以通過Application中的DaoSession獲得蜡歹。
StudentDao studentDao = ((MyApplication)getApplication()).getDaoSession().getStudentDao();

//增
studentDao.insert(student);   //插入一條數(shù)據(jù)
studentDao.insertOrReplace(student);   //增加一條數(shù)據(jù),如果有這條數(shù)據(jù)則更新

//刪
studentDao.delete(student);
studentDao.deleteByKey(1L);

//改
studentDao.update(student);

//查
List<Student> studentList = studentDao.loadAll();   //獲取所有數(shù)據(jù)
studentDao.queryRaw("where age>?","18"); //直接寫查詢條件
studentDao.loadByRowId(1);  //根據(jù)ID查詢
QueryBuilder builder = userDao.queryBuilder();
return  builder.where(StudentDao.Properties.Age.gt(18)).build().list();  //通過QueryBuilder拼查詢條件

Realm

Realm和GreenDAO有很大的不同擅这,Realm本身就是一種數(shù)據(jù)庫(kù)仲翎,而且是可以支持跨平臺(tái)的數(shù)據(jù)庫(kù)铛漓,比SQLite更輕量級(jí),速度也更快玫坛,支持JSON格式湿镀、數(shù)據(jù)變更通知伐憾、數(shù)據(jù)同步等等特性。下面介紹它的簡(jiǎn)單使用流程蒸矛。

  • 引入依賴
    Realm同樣需要在工程的build.gradle文件和Module的build.gradle文件配置依賴。
    工程的build.gradle:
buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
        classpath "io.realm:realm-gradle-plugin:5.0.0"     //realm插件路徑
    }
}

Module中的build.gradle只需引入插件即可:

apply plugin: 'realm-android'
  • 初始化
    Realm的初始化也推薦在Application中進(jìn)行斩祭,例子如下:
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Realm.init(this);
        RealmConfiguration configuration = new RealmConfiguration
                .Builder()
                .name("test.realm")    //設(shè)置數(shù)據(jù)庫(kù)名稱
                .migration(new RealmMigration() {            //設(shè)置升級(jí)策略
                    @Override
                    public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {

                        RealmSchema schema = realm.getSchema();

                        switch ((int) oldVersion){
                            case 0:
                                schema.create("Person")
                                        .addField("name", String.class)
                                        .addField("age", int.class);
                                oldVersion++;
                            case 1:
                                schema.get("Person")
                                        .addField("id", long.class, FieldAttribute.PRIMARY_KEY)
                                        .addRealmObjectField("favoriteDog", schema.get("Dog"))
                                        .addRealmListField("dogs", schema.get("Dog"));
                                oldVersion++;
                        }
                    }
                })
                .deleteRealmIfMigrationNeeded()   //合并需要?jiǎng)h除可以刪除
                .schemaVersion(4)                //設(shè)置版本號(hào)
                .inMemory()                     //設(shè)置為內(nèi)存數(shù)據(jù)庫(kù)
                .readOnly()                     //設(shè)置數(shù)據(jù)庫(kù)只讀
                .build();
        Realm.setDefaultConfiguration(configuration);
    }
}

首先調(diào)用Realm.init(this),如果需要設(shè)置一些初始化功能蚊伞,可以創(chuàng)建一個(gè)RealmConfiguration时迫,代碼中可以看到谓晌,RealmConfiguration可以指定很多功能,比如數(shù)據(jù)庫(kù)名稱溺欧、升級(jí)策略柏肪、版本號(hào)烦味、以及設(shè)置只讀、內(nèi)存數(shù)據(jù)庫(kù)等等柏靶。然后把這個(gè)RealmConfiguration設(shè)置為Realm的默認(rèn)配置即可溃论。

  • 編寫Entity類
    Realm的實(shí)體類需要繼承RealmObject,也有一些功能性的注解可以使用炬转,如下是一個(gè)實(shí)體類:
public class Student extends RealmObject{
    @PrimaryKey
    long id;
    String name;
    int age;
    String grades;

    RealmList<Course> courses;

    public RealmList<Course> getCourses() {
        return courses;
    }

    public void setCourses(RealmList<Course> courses) {
        this.courses = courses;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = 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 getGrades() {
        return grades;
    }

    public void setGrades(String grades) {
        this.grades = grades;
    }
}

其中@PrimaryKey表示主鍵扼劈,但是沒有自動(dòng)增加的功能乎婿,需要自己實(shí)現(xiàn)。學(xué)生和課程關(guān)系是用RealmList表示的捍靠,這種關(guān)系和SQLite中的一對(duì)多榨婆,多對(duì)多有可能是不太一樣的,但還需要進(jìn)一步研究才能確定谊迄。Course類也是類似的烟央,不再貼代碼了。

  • 增刪改查
    Realm的增刪改查是通過Realm類的實(shí)例來實(shí)現(xiàn)的粮呢,并且必須在事務(wù)中進(jìn)行而且不能跨線程操作啄寡,先看代碼:
Realm realm = Realm.getDefaultInstance();    //獲取默認(rèn)配置的Realm實(shí)例

//或者這樣隨時(shí)用一個(gè)RealmConfiguration參數(shù)生成一個(gè)Realm
//realm = Realm.getInstance(new RealmConfiguration.Builder().name("othor.realm").build()); 

//增
//增加3個(gè)課程
        realm.beginTransaction();      //必須先開事務(wù)
        List<Course> courseList = new ArrayList<>();
        Course course1 = realm.createObject(Course.class);    //使用createObject方法創(chuàng)建對(duì)象
        course1.setName("數(shù)學(xué)");
        course1.setId(0);
        courseList.add(course1);
        Course course2 = new Course();  //用new創(chuàng)建對(duì)象哩照,這個(gè)對(duì)象對(duì)于Realm是非托管的
        course2.setName("語文");
        course2.setId(1);
        realm.copyToRealm(course2); //new 出的對(duì)象必須使用copyToRealm方法“拷貝”給Realm飘弧,不能直接插入,這也是個(gè)值得研究的問題
        courseList.add(course2);
        Course course3 = realm.createObject(Course.class);
        course3.setName("英語");
        course3.setId(2);
        courseList.add(course3);
        realm.insert(courseList);              //批量插入
        realm.commitTransaction();       //關(guān)閉事務(wù)

       //或者用回調(diào)的方式操作蹋岩,可以代替事務(wù)開關(guān)
        realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                Student student = new Student();
                student.setName("小明");
                student.setAge(18);
                student.setGrades("一年級(jí)");
                realm.copyToRealm(student);
            }
        });
        
//刪
         realm.beginTransaction();
         RealmResults<Student> students = realm.where(Student.class).findAll();
         students.get(0).deleteFromRealm();    //通過實(shí)體類自己的方法刪除
         students.deleteFirstFromRealm();       //通過RealmResults刪除
         students.deleteLastFromRealm();    //通過RealmResults刪除
         students.deleteFromRealm(1);   //通過RealmResults刪除
         realm.commitTransaction();

//改
          realm.beginTransaction();
          RealmResults<Student> students = realm.where(Student.class).findAll();
          students.get(0).setName("更新名字");     //直接查出一個(gè)數(shù)據(jù)修改就行
          realm.commitTransaction();
         
//查
          //查的方式很多剪个,比如上面的findAll方法版确,還有下面的equalTo绒疗、between,查詢某個(gè)字段等于某個(gè)值或在某個(gè)區(qū)間等等惕虑,這種方法有很多很多
          Student student = realm.where(Student.class).equalTo("age",18).findFirst();
          RealmQuery<Student> studentList = realm.where(Student.class).between("age",10,18);

如上就是GreenDAO和Realm的簡(jiǎn)單使用流程,更深入的分析健提,可以關(guān)注后續(xù)文章伟叛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末统刮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子暗膜,更是在濱河造成了極大的恐慌辉哥,老刑警劉巖醋旦,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件会放,死亡現(xiàn)場(chǎng)離奇詭異咧最,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)滥搭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門瑟匆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栽惶,“玉大人,你說我怎么就攤上這事冕象≈” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵膀估,是天一觀的道長(zhǎng)只锻。 經(jīng)常有香客問我,道長(zhǎng)捐寥,這世上最難降的妖魔是什么祖驱? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任捺僻,我火速辦了婚禮匕坯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锹雏。我一直安慰自己术奖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布佣耐。 她就那樣靜靜地躺著兼砖,像睡著了一般选侨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上戏挡,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天褐墅,我揣著相機(jī)與錄音,去河邊找鬼竟贯。 笑死逝钥,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的持际。 我是一名探鬼主播哗咆,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼晌柬,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼年碘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起闷祥,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎箱硕,沒想到半個(gè)月后剧罩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡幕与,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年啦鸣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了来氧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凫碌,死狀恐怖胃榕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情苦掘,我是刑警寧澤赐写,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布挺邀,位于F島的核電站,受9級(jí)特大地震影響泣矛,放射性物質(zhì)發(fā)生泄漏禾蚕。R本人自食惡果不足惜换淆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一倍试、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧涮母,春花似錦躁愿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至剧防,卻和暖如春峭拘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鸡挠。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工拣展, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留备埃,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓于毙,卻偏偏與公主長(zhǎng)得像辅搬,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子堪遂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,517評(píng)論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理介蛉,服務(wù)發(fā)現(xiàn),斷路器溶褪,智...
    卡卡羅2017閱讀 134,600評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,748評(píng)論 6 342
  • 白茶清歡無別事竿滨,我在等風(fēng)也等你。 01 有人說捏境,青春是一場(chǎng)盛大的暗流涌動(dòng)于游。 而周沫的青春,卻只是兀自一人的漂流贰剥。 ...
    芍安閱讀 1,924評(píng)論 16 55
  • 不知不覺我已經(jīng)走入了七年之癢,說句實(shí)話担忧,激情不再芹缔,看著老公更多的是親人,呆在身邊會(huì)忽視瓶盛,離開遠(yuǎn)了才會(huì)想起最欠。 其實(shí)也...
    ACTIONCLUB知行樂閱讀 250評(píng)論 3 3