Realm中文文檔(翻譯)

目錄

Getting Started
Getting Help
Models
Relationships
Writes
Queries
Realms
Threading
Schemas
JSON
Notifications
Migrations
Encryption
Working With Android
Other Libraries
Testing and Debugging
Current Limitations
Best Practices
Recipes
FAQ
Api Reference

開始

realm-java文檔鏈接

先決條件

我們現(xiàn)在只支持Android里面用到的Java語法
Android Studio >= 1.5.1
最新的Android sdk版本
JDK version >=7.
我們支持從API 9(2.3姜餅)以上的版本

安裝

Realm 是被作為一個gradle插件來安裝的
安裝Realm為gradle插件需要2步

  • 第一步:加入下面class path dependency到工程目錄下的build.gradle文件中
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "io.realm:realm-gradle-plugin:1.1.0"
    }
}

工程目錄下的build.gradle文件在這里


工程目錄下的build.gradle
工程目錄下的build.gradle
  • 第二步:在應(yīng)用目錄下的build.gradle文件中添加 realm-android 插件到application的頂部
apply plugin: 'realm-android'

application級別的build.gradle在這


應(yīng)用目錄下的build.gradle
應(yīng)用目錄下的build.gradle

一旦這兩個有所改動瞬矩,簡單地刷新一下你的gradle dependencies就可以了卓囚。如果你從一個更高的版本到v0.88版本提升帮哈,那么你也需要clean一下你的gradle工程(命令./gradlew clean)來移除任何之前緩存的安裝的東西

想查看兩個文件build.gradle的簡單例子在這里

其他build systems

maven 或者ant 構(gòu)建系統(tǒng),不支持。如果你想看關(guān)于對這些構(gòu)建系統(tǒng)的支持滞乙,下面有,請向我們表明你的興趣,我們會權(quán)衡而定

在是否實(shí)現(xiàn)ant和maven支持上枯夜,你的意見是很有決定性的

1.0.0版本之后,eclipse是不支持的艰山,請你去用Android studio

混淆

一個混淆配置在中realm library已經(jīng)支持湖雹。這就意味著你不需要加入任何realm 混淆規(guī)則進(jìn)混淆文件配置里面。(意思就是說曙搬,你不用混淆了摔吏,少操這份心)

Realm Browser

我們提供一個提供了一個獨(dú)立的叫Realm Brower 的mac app來讀realm數(shù)據(jù)庫文件(生成的.realm數(shù)據(jù)庫文件,就可以用這個app來打開查看)

Realm Browser

你可以可以使用menu item tools->Generate demo databases集成一個帶用例的測試數(shù)據(jù)庫demo

如果你需要查找你app的realm 文件纵装,可以去看StackOverflow的對具體相關(guān)說明的回答

Realm Brower在Mac app商店上面是有的征讲,或者你可以從我們的Github網(wǎng)頁跳過去下載

這個瀏覽器現(xiàn)在不能在Linux和window上面運(yùn)行。在這些平臺上你可以使用Stetho-Realm來代替橡娄。Stetho 是一個Android的Facebook創(chuàng)建的Google瀏覽器調(diào)試橋

API參考

你可以查閱我們所有的API參考的類诗箍、方法或者其他更多

例子

看一看我們的例子一邊能夠了解Realm在一個app中實(shí)際操作中的使用。你只需要用Android studio導(dǎo)入工程挽唉,運(yùn)行就行了

introExample包含了用例和使用最新的api

gridviewExample是不太重要扳还,只是為了向我們展示如何使用Realm作為gridview的后備數(shù)據(jù)庫。它也向你展示如何用json和gson來寫入數(shù)據(jù)庫橱夭,如果使用ABI分叉來最小化你APK的大小

theadExample是一個簡單的向我們展示Realm在多線程環(huán)境中怎么運(yùn)行app

adapterExample向我們展示如何使用RealmBaseAdapterRealmRecyclerViewAdapter來讓Realm和Android的ListViewRecyclerView一起使用變得優(yōu)雅

jsonExample闡述了如何使用新的Realm Json工具

encryptionExample向你展示如何加密Realms

rxJavaExamlple向你展示Realm如何和Rxjava一起使用

unitTestExample展示了使用Realm怎么寫單元測試

獲得幫助

需要代碼上的幫助么氨距?去StackOverflow上面問吧。我們會很積極的查看和回答在上面的問題
有一個bug需要提交棘劣?提一個issue給我們俏让。如果可能,我們會把它加入進(jìn)去。一個完善的log,Realm文件首昔,和一個工程都可以作為issue給我們看
有功能上的問題寡喝?提一個issue給我們,告訴我們哪些功能應(yīng)該做勒奇,和為什么你想要這個功能
想follow我們接下來新的功能预鬓?看我們的changelog。這個log展示了最新加入的東西和我們即將要發(fā)布的東西赊颠,還有Realm的發(fā)展歷程

模型

Realm model類的創(chuàng)建需要繼承RealmObject基類

public class User extends RealmObject {

    private String          name;
    private int             age;

    @Ignore
    private int             sessionId;

    // Standard getters & setters generated by your IDE…
    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 int    getSessionId() { return sessionId; }
    public void   setSessionId(int sessionId) { this.sessionId = sessionId; }
}

一個Realm model類也支持public 格二、protectedprivate變量和自定義方法

public class User extends RealmObject {

    public String name;

    public boolean hasLongName() {
      return name.length() > 7;
    }

    @Override
    public boolean equals(Object o) {
      // Custom equals comparison
    }
}

變量類型

Field types
Realm支持這些類型:boolean, byte, short, int, long, float, double, String, Date and byte[]竣蹦。在realm中顶猜,integer類型 byte、short痘括、int和long其實(shí)都是最終映射為long類型长窄。除此之外,RealmObject的子類和RealmList<? extends RealmObject>都支持模型類的關(guān)聯(lián)(就是可以成員變量是關(guān)聯(lián)的其他類纲菌,而不僅僅是基礎(chǔ)類型)

包裝類Boolean,Byte,Short,Integer,Long, Float and Double都可以在model類里面使用挠日。使用這些類,也可以置空翰舌,設(shè)置值為null

非空變量和null值

在某些情況下肆资,null不是一個恰當(dāng)?shù)淖兞恐怠?strong>@Required注解能夠檢測并報(bào)null值的錯誤。只有Boolean, Byte, Short, Integer, Long, Float, Double, String, byte[] and Date 能被@Required注解灶芝。當(dāng)其他類型用@Required注解的時候編譯會失敗郑原。主鍵類型的變量和RealmList類型的變量自身就是非空的、必要的(意思就是主鍵和RealmList肯定已經(jīng)不能為空了夜涕,已經(jīng)有Required屬性了)犯犁。RealmObject的變量是可為空的

ignoring 屬性

@Ignore注解表明一個變量不是必要的,是可有可無的女器。Ignore變量在你寫入你model之外的其他屬性而你又不想在太多特別的情況下去處理這些沒有太大用處的屬性的時候是很有用的(意思就是酸役,那些是可忽略的,比如購物車?yán)锩婷總€東西的價格是必要的驾胆,但是總價就不是必要的涣澡,因?yàn)榭梢酝扑愠鰜恚敲纯偨Y(jié)這個屬性就是可以ignore的丧诺,不需要寫入數(shù)據(jù)庫)

Auto-Updating Objects

RealmObject是動態(tài)的入桂、自動更新到底層的數(shù)據(jù)去的,這意味著你不需要刷新驳阎,就能修改抗愁。影響查詢的修改會被立馬反射到結(jié)果中去馁蒂。(這里涉及多線程的問題,一邊在修改一邊在查詢蜘腌,只要你這邊修改了沫屡,那邊插敘的結(jié)果就是最新修改的,這就是動態(tài)的撮珠、自動更新的意思)

realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        Dog myDog = realm.createObject(Dog.class);
        myDog.setName("Fido");
        myDog.setAge(1);
    }
});
Dog myDog = realm.where(Dog.class).equalTo("age", 1).findFirst();

realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        Dog myPuppy = realm.where(Dog.class).equalTo("age", 1).findFirst();
        myPuppy.setAge(2);
    }
});

myDog.getAge(); // => 2

所有RealmObject和RealmResults的性能不僅讓Realm快和高效沮脖,而且還讓你的代碼變得更簡單更靈活。例如芯急,如果你的Activity或者Fragment關(guān)聯(lián)了一個RealmObject或者RealmResult實(shí)例勺届,在更新UI的時候你不需要擔(dān)心刷新或者重新獲取

你可以訂閱Realm提醒,知道什么時候Realm數(shù)據(jù)被更新了志于,在你app UI應(yīng)該被更新的時候提醒你

Indexing屬性

Indexing properties

The annotation @Index will add a search index to the field. This will make inserts slower and the data file larger but queries will be faster. So it’s recommended to only add index when optimizing specific situations for read performance. We support indexing: String, byte, short, int, long, boolean and Date fields.

Primary keys
To promote a field to primary key, you use the annotation @PrimaryKey, and the field type has to be either string (String) or integer (byte, short, int, or long) and its boxed variants (Byte, Short, Integer, and Long). It is not possible to use multiple fields (compound key) as a primary key. Using a string field as a primary key implies that the field is indexed (the annotation @PrimaryKey implicitly sets the annotation @Index).

Using primary keys makes it possible to use the copyToRealmOrUpdate() method, which will look for an existing object with this primary key, and update it if one is found; if none is found, it will create a new object instead. When calling copyToRealmOrUpdate() on classes without primary keys, an exception will be thrown.

Using primary keys has an effect on the performance. Creating and updating object will be a little slower while querying is expected to be a bit faster. It is hard to give numbers as the changes in performance depend on the size of your dataset.

When calling Realm.createObject(), it will return a new object with all fields set to the default value. In this case, there might be a conflict with an existing object whose primary key field is the default value. To avoid this, it is suggested to create an unmanaged object, set values of the fields, and then copy it to Realm by copyToRealm() method.

final MyObject obj = new MyObject();
obj.setId(42);
obj.setName("Fish");
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
// This will create a new object in Realm or throw an exception if the
// object already exists (same primary key)
// realm.copyToRealm(obj);

    // This will update an existing object with the same primary key
    // or create a new object if an object with no primary key = 42
    realm.copyToRealmOrUpdate(obj);
}

});
For String (String) and boxed integer (Byte, Short, Integer, and Long), Primary keys can have the value null unless the @PrimaryKey annotation is additionally combined with @Required annotation.

Customizing Objects
It is possible to use RealmObjects almost like POJOs. Extending from RealmObject, you can let the fields be public, and use simple assignments instead of setters and getter. An example of such a model class is:

public class Dog extends RealmObject {
public String name;
public int age;
}
You can use Dog like any other class. In order to create a managed Dog object in Realm, you can use the createObject() or copyToRealm() methods.

realm.executeTransaction(new Realm.Transaction() {
@Overrride
public void execute(Realm realm) {
Dog dog = realm.createObject(Dog.class);
dog.name = "Fido";
dog.age = 5;
}
};
You can add logic to your setters and getters if that fits your needs better. This can be useful if you wish to validate values before storing them in your Realm. Moreover, you can easily add custom methods to your RealmObjects.

Limitations
Currently there’s no support for final, transient and volatile fields. This is mainly to avoid discrepancies between how an object would behave as managed by Realm or unmanaged.

Realm model classes are not allowed to extend any other object than RealmObject. If declared, the default constructor (constructor with no parameters) must always be empty. The reason is that a default contructor will call methods which assume a Realm instance is present. But that instance isn’t create before the contructor returns. You can add other constructors for your convienence.

RealmModel interface
An alternative to extending the RealmObject base class is implementing the RealmModel interface and adding the @RealmClass annotation.

@RealmClass
public class User implements RealmModel {

}
All methods available on RealmObject are then available through static methods.

// With RealmObject
user.isValid();
user.addChangeListener(listener);

// With RealmModel
RealmObject.isValid(user);
RealmObject.addChangeListener(user, listener);
Relationships

Any two RealmObjects can be linked together.

public class Email extends RealmObject {
private String address;
private boolean active;
// ... setters and getters left out
}

public class Contact extends RealmObject {
private String name;
private Email email;
// ... setters and getters left out
}
Relationships are generally cheap in Realm. This means that following a link is not expensive in terms of speed, and the internal presentation of relationships is highly efficient in terms of memory consumption.

Many-to-One
Simply declare a property with the type of one of you RealmObject subclasses:

public class Contact extends RealmObject {
private Email email;
// Other fields…
}
Each contact (instance of Contact) have either 0 or 1 email (instance of Email). In Realm, nothing prevent you from using the same email object in multiple contacts, and the model above can be a many-to-one relationship but often used to model one-to-one relationships.

Setting the RealmObject field to null will clear the reference but the object will not be deleted from the Realm.

Many-to-Many
You can establish a relationship to any number of objects from a single object via a RealmList<T> field declaration. For example, consider a contact with multiple email addresses:

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

public class Email extends RealmObject {
public String address;
public boolean active;
}
RealmLists are basically containers of RealmObjects, and a RealmList behaves very much like a regular Java List. There are no limitations in Realm to use the same object twice (or more) in different RealmLists, and you can use this to model both one-to-many, and many-to-many relationships.

You can create objects, and use RealmList.add() to add the Email objects to the Contact object:

realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
Contact contact = realm.createObject(Contact.class);
contact.name = "John Doe";

    Email email1 = realm.createObject(Email.class);
    email1.address = "john@example.com";
    email1.active = true;
    contact.emails.add(email1);

    Email email2 = realm.createObject(Email.class);
    email2.address = "jd@example.com";
    email2.active = false;
    contact.emails.add(email2);
}

});
It is possible to declare recursive relationships which can be useful when modeling certain types of data.

public class Person extends RealmObject {
public String name;
public RealmList<Person> friends;
// Other fields…
}
Setting the value to null for a RealmList field will clear the list. That is, the list will be empty (length zero), but no objects have been deleted. The getter for a RealmList will never return null. The returned object is always a list but the length might be zero.

Link queries
It is possible to query links or relationships. Consider the model below:

public class Person extends RealmObject {
private String id;
private String name;
private RealmList<Dog> dogs;
// getters and setters
}

public class Dog extends RealmObject {
private String id;
private String name;
private String color;
// getters and setters
}
Each Person object has multiple dog relationships as shown in this table diagram:

Table Diagram

Let’s find some persons with link queries …

// persons => [U1,U2]
RealmResults<Person> persons = realm.where(Person.class)
.equalTo("dogs.color", "Brown")
.findAll();
First of all, notice that the field name in the equalsTo condition contains the path through the relationships (separated by period .).

The query above should read, find all Persons who have dogs who are ‘Brown’. It is important to understand that the result will contain the Dog objects which do not fulfill the condition since they are part of the Person’s object:

persons.get(0).getDogs(); // => [A,B]
persons.get(1).getDogs(); // => [B,C,D]
This can be further examined by the following two queries.

// r1 => [U1,U2]
RealmResults<Person> r1 = realm.where(Person.class)
.equalTo("dogs.name", "Fluffy")
.findAll();

// r2 => [U1,U2]
RealmResults<Person> r2 = r1.where()
.equalTo("dogs.color", "Brown")
.findAll();
Notice how the first query returned both Person objects because the condition matched both persons. Each Person in the query result contains a list of Dog objects - all of their dog objects (even ones that do not fulfill the original query condition). Remember, we’re searching for people who have particular kinds of dogs (names and colors), not the actual dogs themselves. Therefore, the second query will be evaluated against the first Person query result (r1) and each of the Persons dogs. The second query also matches both persons as well, but this time it’s because of the color of the dog.

Let’s dig a little deeper to help solidify this concept. Please review the following example:

// r1 => [U1,U2]
RealmResults<Person> r1 = realm.where(Person.class)
.equalTo("dogs.name", "Fluffy")
.equalTo("dogs.color", "Brown")
.findAll();

// r2 => [U2]
RealmResults<Person> r2 = realm.where(Person.class)
.equalTo("dogs.name", "Fluffy")
.findAll()
.where()
.equalTo("dogs.color", "Brown")
.findAll();
.where()
.equalTo("dogs.color", "Yellow")
.findAll();
The first query should read, find all Persons who have dogs named ‘Fluffy’ and also find all Persons who have dogs who are ‘Brown’ and then give me the intersection of the two. The second query should read, find all Persons who have dogs named ‘Fluffy’. Then, given that result set, find all Persons who have dogs whose color is ‘Brown’ and given that result set find all Persons who have dogs whose color is ‘Yellow’.

Let’s take a look at the query behind r1 to fully understand what is happening. The two conditions are equalTo("dogs.name", "Fluffy") and equalTo("dogs.color", "Brown"). The first condition is fulfilled for U1 and U2 - this is set C1. The second condition is also fulfilled for U1 and U2 - this is set C2. The logical-and in the query is the same as an intersection of the two sets C1 and C2. The intersection between C1 and C2 is U1 and U2. Therefore, r1 is U1 and U2.

The query behind r2 is different. Let’s begin by breaking this query apart. The first portion of the query looks like this: RealmResults<Person> r2a = realm.where(Person.class).equalTo("dogs.name", "Fluffy").findAll();. It matches U1 and U2. Then, r2b = r2a.where().equalTo("dogs.color", "Brown").findAll(); also matches U1 and U2 (both persons have brown dogs). The final query, r2 = r2b.where().equalTo("dogs.color", "Yellow").findAll(); matches only U2 since the only person in the brown dog result set that has a Yellow dog is U2.

Writes

Read operations are implicit which means that objects can be accessed and queried at any time. All write operations (adding, modifying, and removing objects) must be wrapped in write transactions. A write transaction can either be committed or cancelled. During the commit, all changes will be written to disk, and the commit will only succeed if all changes can be persisted. By cancelling a write transaction, all changes will be discarded. Using write transactions, your data will always be in a consistent state.

Write transactions are also used to ensure thread safety:

// Obtain a Realm instance
Realm realm = Realm.getDefaultInstance();

realm.beginTransaction();

//... add or update objects here ...

realm.commitTransaction();
While working with your RealmObjects inside a write transaction, you might end up in a situation where you wish to discard the change. Instead of committing it, and then reverting it, you can simply cancel the write transaction:

realm.beginTransaction();
User user = realm.createObject(User.class);

// ...

realm.cancelTransaction();
Please note that write transactions block each other. This can cause ANR errors if you are creating write transactions on both the UI and background threads at the same time. To avoid this, use async transactions when creating write transactions on the UI thread.

Thanks to Realm’s MVCC architecture, reads are not blocked while a write transaction is open! This means that unless you need to make simultaneous transactions from many threads at once, you can favor larger transactions that do more work over many fine-grained transactions. When you commit a write transaction to a Realm, all other instances of that Realm will be notified, and be updated automatically.

Read & write access in Realm is ACID.

Creating objects
Because RealmObjects are strongly tied to a Realm, they should be instantiated through the Realm directly:

realm.beginTransaction();
User user = realm.createObject(User.class); // Create a new object
user.setName("John");
user.setEmail("john@corporation.com");
realm.commitTransaction();
Alternatively you can create an instance of an object first and add it later using realm.copyToRealm(). Realm supports as many custom constructors as you like as long as one of them is a public no arguments constructor.

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

// Copy the object to Realm. Any further changes must happen on realmUser
realm.beginTransaction();
User realmUser = realm.copyToRealm(user);
realm.commitTransaction();
When using realm.copyToRealm() it is important to remember that only the returned object is managed by Realm, so any further changes to the original object will not be persisted.

Transaction blocks
Instead of manually keeping track of realm.beginTransaction(), realm.commitTransaction(), and realm.cancelTransaction() you can use the realm.executeTransaction() method, which will automatically handle begin/commit, and cancel if an error happens.

realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
User user = realm.createObject(User.class);
user.setName("John");
user.setEmail("john@corporation.com");
}
});
Asynchronous Transactions
As transactions are blocked by other transactions it can be an advantage to do all writes on a background thread in order to avoid blocking the UI thread. By using an asynchronous transaction, Realm will run that transaction on a background thread and report back when the transaction is done.

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.
}
});
OnSuccess and OnError callbacks are both optional, but if provided they will be called when the transaction completes successfully or fails, respectively. Callbacks are controlled by the Looper, so they are only allowed on Looper threads.

RealmAsyncTask transaction = 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");
}
}, null);
An asynchronous transaction is represented by the RealmAsyncTask object. This object can be used to cancel any pending transaction if you are quitting the Activity/Fragment before the transaction is completed. Forgetting to cancel a transaction can crash the app if the callback updates the UI.

public void onStop () {
if (transaction != null && !transaction.isCancelled()) {
transaction.cancel();
}
}
Updating strings and byte arrays
Realm is working on entire fields, and it is not possible to update individual elements of strings or byte arrays. Suppose you need to update the 5th element of a string, you will have to do something like

realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
bytes[] bytes = realmObject.binary;
bytes[4] = 'a';
realmObject.binary = bytes;
}
});
This is due to Realm’s MVCC architecture which avoids mutating existing data in place to ensure that other threads or processes reading the data see it in a consistent state.

Queries

All fetches (including queries) are lazy in Realm, and the data is never copied.
Realm’s query engine uses a Fluent interface to construct multi-clause queries.

Using the User class -

public class User extends RealmObject {

@PrimaryKey
private String          name;
private int             age;

@Ignore
private int             sessionId;

// Standard getters & setters generated by your IDE…
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 int    getSessionId() { return sessionId; }
public void   setSessionId(int sessionId) { this.sessionId = sessionId; }

}
To find all users named John or Peter you would write:

// Build the query looking at all users:
RealmQuery<User> query = realm.where(User.class);

// Add query conditions:
query.equalTo("name", "John");
query.or().equalTo("name", "Peter");

// Execute the query:
RealmResults<User> result1 = query.findAll();

// Or alternatively do the same all at once (the "Fluent interface"):
RealmResults<User> result2 = realm.where(User.class)
.equalTo("name", "John")
.or()
.equalTo("name", "Peter")
.findAll();
This gives you a new instance of the class RealmResults, containing the users with the name John or Peter. Objects are not copied - you get a list of references to the matching objects, and you work directly with the original objects that matches your query. The RealmResults inherits from Java’s AbstractList, and behaves in similar ways. For example, RealmResults are ordered, and you can access the individual objects through an index.

When a query does not have any matches, the returned RealmResults object will not be null, but the size() method will return 0.

If you wish modify or delete any of the objects in a RealmResults, you must do so in a write transaction.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涮因,一起剝皮案震驚了整個濱河市废睦,隨后出現(xiàn)的幾起案子伺绽,更是在濱河造成了極大的恐慌,老刑警劉巖嗜湃,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奈应,死亡現(xiàn)場離奇詭異,居然都是意外死亡购披,警方通過查閱死者的電腦和手機(jī)杖挣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刚陡,“玉大人惩妇,你說我怎么就攤上這事】鹑椋” “怎么了歌殃?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蝙云。 經(jīng)常有香客問我氓皱,道長,這世上最難降的妖魔是什么勃刨? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任波材,我火速辦了婚禮,結(jié)果婚禮上身隐,老公的妹妹穿的比我還像新娘廷区。我一直安慰自己,他們只是感情好贾铝,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布躲因。 她就那樣靜靜地躺著早敬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪大脉。 梳的紋絲不亂的頭發(fā)上搞监,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機(jī)與錄音镰矿,去河邊找鬼琐驴。 笑死,一個胖子當(dāng)著我的面吹牛秤标,可吹牛的內(nèi)容都是我干的绝淡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼苍姜,長吁一口氣:“原來是場噩夢啊……” “哼牢酵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起衙猪,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤馍乙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后垫释,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丝格,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年棵譬,在試婚紗的時候發(fā)現(xiàn)自己被綠了显蝌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡订咸,死狀恐怖曼尊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情脏嚷,我是刑警寧澤骆撇,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站然眼,受9級特大地震影響艾船,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜高每,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一屿岂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鲸匿,春花似錦爷怀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烤惊。三九已至,卻和暖如春吁朦,著一層夾襖步出監(jiān)牢的瞬間柒室,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工逗宜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留雄右,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓纺讲,卻偏偏與公主長得像擂仍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評論 2 354

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