AIDL源碼解析in、out和inout

個人博客地址 http://dandanlove.com/

為什么會想寫這篇文章利花,只因為一個error idl.exe E 4928 5836 type_namespace.cpp:130] 'Book' can be an out type, so you must declare it as in, out or inout. 看過上一篇文章Android:IPC之AIDL的學(xué)習(xí)和總結(jié)的同學(xué)都知道這是因為在AIDL文件中使用非常規(guī)類型作為參數(shù)傳遞的時候沒有標記指向tag,那么到底為什么會是這樣子的呢,作為一個好奇寶寶我想好好看看艰亮。

介紹

官網(wǎng)介紹AIDL的時候上有這么一段話

  • All non-primitive parameters require a directional tag indicating which way the data goes. Either in, out, or inout (see the example below).
  • Primitives are in by default, and cannot be otherwise.
  • Caution: You should limit the direction to what is truly needed, because marshalling parameters is expensive.

大概意思是非默認類型的參數(shù)都需要添加指向標簽in,out或inout挣郭。根據(jù)自己的需求去添加垃杖,因為實現(xiàn)是有代價的。

已知結(jié)論

看過我寫的Android:IPC之AIDL的學(xué)習(xí)和總結(jié)的同學(xué)都知道:

  • in表示輸入型參數(shù)(Server可以獲取到Client傳遞過去的數(shù)據(jù)丈屹,但是不能對Client端的數(shù)據(jù)進行修改)
  • out表示輸出型參數(shù)(Server獲取不到Client傳遞過去的數(shù)據(jù)调俘,但是能對Client端的數(shù)據(jù)進行修改)
  • inout表示輸入輸出型參數(shù)(Server可以獲取到Client傳遞過去的數(shù)據(jù)伶棒,但是能對Client端的數(shù)據(jù)進行修改)。

提出問題

下邊我們就研究一個in彩库,out或inout為什么能代表不同的傳輸方式肤无,為什么實現(xiàn)的代價不一樣。

過程驗證

創(chuàng)建Book.aidl文件

package com.tzx.aidldemo.aidl;
parcelable Book;

創(chuàng)建Book.java文件

package com.tzx.aidldemo.aidl;
public class Book implements Parcelable {
    public int bookId;
    public String bookName;

    public Book() {
    }

    public Book(int bookId, String bookName) {
        this.bookId = bookId;
        this.bookName = bookName;
    }
    //從序列化后的對象中創(chuàng)建原始對象
    protected Book(Parcel in) {
        bookId = in.readInt();
        bookName = in.readString();
    }

    public static final Creator<Book> CREATOR = new Creator<Book>() {
        //從序列化后的對象中創(chuàng)建原始對象
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }
        //指定長度的原始對象數(shù)組
        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };
    //返回當前對象的內(nèi)容描述骇钦。如果含有文件描述符宛渐,返回1,否則返回0眯搭,幾乎所有情況都返回0
    @Override
    public int describeContents() {
        return 0;
    }
    //將當前對象寫入序列化結(jié)構(gòu)中窥翩,其flags標識有兩種(1|0)。
    //為1時標識當前對象需要作為返回值返回鳞仙,不能立即釋放資源寇蚊,幾乎所有情況下都為0.
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(bookId);
        dest.writeString(bookName);
    }

    @Override
    public String toString() {
        return "[bookId=" + bookId + ",bookName='" + bookName + "']";
    }
}

創(chuàng)建aidl接口文件IBookManager.aidl文件

package com.tzx.aidlinout.aidl;
import com.tzx.aidlinout.aidl.Book;
interface IBookManager {
    Book addInBook(in Book book);
    Book addOutBook(out Book book);
    Book addInoutBook(inout Book book);
}

創(chuàng)建遠程服務(wù)

//將bookId都改為-1,在bookName后面都添加參數(shù)的tag標記
public class BookManagerService extends Service {
    private CopyOnWriteArrayList list = new CopyOnWriteArrayList();
    private IBinder mBinder = new IBookManager.Stub(){

        @Override
        public Book addInBook(Book book) throws RemoteException {
            book.bookId = -1;
            book.bookName = book.bookName + "-in";
            list.add(book);
            return book;
        }

        @Override
        public Book addOutBook(Book book) throws RemoteException {
            book.bookId = -1;
            book.bookName = book.bookName + "-out";
            list.add(book);
            return book;
        }

        @Override
        public Book addInoutBook(Book book) throws RemoteException {
            book.bookId = -1;
            book.bookName = book.bookName + "-inout";
            list.add(book);
            return book;
        }

        @Override
        public List<Book> getBookList() throws RemoteException {
            return list;
        }
    };
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

在創(chuàng)建上面的文件的過程中棍好,遇到不太清楚的或者編譯出現(xiàn)Error的仗岸,可以參考上一篇文章Android:IPC之AIDL的學(xué)習(xí)和總結(jié)

具體方法調(diào)用的Activity就不寫全部代碼了借笙,我們看看三種方法的調(diào)用

@Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.book_in:
                try {
                    int bookId = Integer.parseInt(bookIdET.getText().toString());
                    String bookName = bookNameET.getText().toString();
                    if (bookId <= 0 || TextUtils.isEmpty(bookName)) return;
                    StringBuilder builder = new StringBuilder();
                    //LogUtils.d("-----------book_in-----------------");
                    Book book0 = new Book(bookId, bookName);
                    String source = "source:" + book0.toString();
                    //LogUtils.d(source);
                    builder.append(source);
                    builder.append('\n');
                    String result = "result:" + bookManager.addInBook(book0).toString();
                    //LogUtils.d(result);
                    builder.append(result);
                    builder.append('\n');
                    source = "source" + book0.toString();
                    //LogUtils.d(source);
                    builder.append(source);
                    //LogUtils.d("**************book_in****************");
                    bookinfoTV.setText(builder.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            case R.id.book_out:
                try {
                    int bookId = Integer.parseInt(bookIdET.getText().toString());
                    String bookName = bookNameET.getText().toString();
                    if (bookId <= 0 || TextUtils.isEmpty(bookName)) return;
                    StringBuilder builder = new StringBuilder();
                    //LogUtils.d("-----------book_out-----------------");
                    Book book0 = new Book(bookId, bookName);
                    String source = "source:" + book0.toString();
                    //LogUtils.d(source);
                    builder.append(source);
                    builder.append('\n');
                    String result = "result:" + bookManager.addOutBook(book0).toString();
                    //LogUtils.d(result);
                    builder.append(result);
                    builder.append('\n');
                    source = "source" + book0.toString();
                    //LogUtils.d(source);
                    builder.append(source);
                    //LogUtils.d("**************book_out****************");
                    bookinfoTV.setText(builder.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            case R.id.book_inout:
                try {
                    int bookId = Integer.parseInt(bookIdET.getText().toString());
                    String bookName = bookNameET.getText().toString();
                    if (bookId <= 0 || TextUtils.isEmpty(bookName)) return;
                    StringBuilder builder = new StringBuilder();
                    //LogUtils.d("-----------book_inout-----------------");
                    Book book0 = new Book(bookId, bookName);
                    String source = "source:" + book0.toString();
                    //LogUtils.d(source);
                    builder.append(source);
                    builder.append('\n');
                    String result = "result:" + bookManager.addInoutBook(book0).toString();
                    //LogUtils.d(result);
                    builder.append(result);
                    builder.append('\n');
                    source = "source" + book0.toString();
                    //LogUtils.d(source);
                    builder.append(source);
                    //LogUtils.d("**************book_inout****************");
                    bookinfoTV.setText(builder.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
        }
    }

創(chuàng)建好上面三個文件后扒怖,我們編譯整個項目工程(PS:生成aidl接口實現(xiàn)類)。

運行結(jié)果
[圖片上傳失敗...(image-ed056-1524796700960)]

下邊是與結(jié)果相對應(yīng)的Log輸出

14962-14962/com.tzx.aidlinout D/xxx: -----------book_in-----------------
14962-14962/com.tzx.aidlinout D/xxx: source:[bookId=1212,bookName=C++]
14962-14962/com.tzx.aidlinout D/xxx: result:[bookId=-1,bookName=C++-in]
14962-14962/com.tzx.aidlinout D/xxx: source[bookId=1212,bookName=C++]
14962-14962/com.tzx.aidlinout D/xxx: **************book_in****************
14962-14962/com.tzx.aidlinout D/xxx: -----------book_out-----------------
14962-14962/com.tzx.aidlinout D/xxx: source:[bookId=1212,bookName=C++]
14962-14962/com.tzx.aidlinout D/xxx: result:[bookId=-1,bookName=null-out]
14962-14962/com.tzx.aidlinout D/xxx: source[bookId=-1,bookName=null-out]
14962-14962/com.tzx.aidlinout D/xxx: **************book_out****************
14962-14962/com.tzx.aidlinout D/xxx: -----------book_inout-----------------
14962-14962/com.tzx.aidlinout D/xxx: source:[bookId=1212,bookName=C++]
14962-14962/com.tzx.aidlinout D/xxx: result:[bookId=-1,bookName=C++-inout]
14962-14962/com.tzx.aidlinout D/xxx: source[bookId=-1,bookName=C++-inout]
14962-14962/com.tzx.aidlinout D/xxx: **************book_inout****************

實際結(jié)果與我們已知結(jié)論一致业稼!盗痒!

但問題我們還沒有解決,我們繼續(xù)看代碼低散,其實所有的實現(xiàn)都是在改接口實現(xiàn)類中IBookManager.java

源碼解析

package com.tzx.aidlinout.aidl;
public interface IBookManager extends android.os.IInterface {
    public com.tzx.aidlinout.aidl.Book addInBook(
        com.tzx.aidlinout.aidl.Book book) throws android.os.RemoteException;

    public com.tzx.aidlinout.aidl.Book addOutBook(
        com.tzx.aidlinout.aidl.Book book) throws android.os.RemoteException;

    public com.tzx.aidlinout.aidl.Book addInoutBook(
        com.tzx.aidlinout.aidl.Book book) throws android.os.RemoteException;

    public java.util.List<com.tzx.aidlinout.aidl.Book> getBookList()
        throws android.os.RemoteException;

    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.tzx.aidlinout.aidl.IBookManager {
        private static final java.lang.String DESCRIPTOR = "com.tzx.aidlinout.aidl.IBookManager";
        static final int TRANSACTION_addInBook = (android.os.IBinder.FIRST_CALL_TRANSACTION +
            0);
        static final int TRANSACTION_addOutBook = (android.os.IBinder.FIRST_CALL_TRANSACTION +
            1);
        static final int TRANSACTION_addInoutBook = (android.os.IBinder.FIRST_CALL_TRANSACTION +
            2);
        static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION +
            3);

        /** Construct the stub at attach it to the interface. */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.tzx.aidlinout.aidl.IBookManager interface,
         * generating a proxy if needed.
         */
        public static com.tzx.aidlinout.aidl.IBookManager asInterface(
            android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }

            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);

            if (((iin != null) &&
                    (iin instanceof com.tzx.aidlinout.aidl.IBookManager))) {
                return ((com.tzx.aidlinout.aidl.IBookManager) iin);
            }

            return new com.tzx.aidlinout.aidl.IBookManager.Stub.Proxy(obj);
        }

        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data,
            android.os.Parcel reply, int flags)
            throws android.os.RemoteException {
            switch (code) {
            case INTERFACE_TRANSACTION: {
                reply.writeString(DESCRIPTOR);

                return true;
            }

            case TRANSACTION_addInBook: {
                data.enforceInterface(DESCRIPTOR);
                //聲明輸入的參數(shù)_arg0的引用
                com.tzx.aidlinout.aidl.Book _arg0;
                //并根據(jù)輸入的數(shù)據(jù)為其創(chuàng)建對象
                if ((0 != data.readInt())) {
                    _arg0 = com.tzx.aidlinout.aidl.Book.CREATOR.createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                //獲取調(diào)用this.addInBook方法返回的_result
                com.tzx.aidlinout.aidl.Book _result = this.addInBook(_arg0);
                reply.writeNoException();
                //并向reply中寫入返回值_result
                if ((_result != null)) {
                    reply.writeInt(1);
                    _result.writeToParcel(reply,
                        android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                } else {
                    reply.writeInt(0);
                }

                return true;
            }

            case TRANSACTION_addOutBook: {
                data.enforceInterface(DESCRIPTOR);
                //聲明輸入的參數(shù)_arg0的引用
                com.tzx.aidlinout.aidl.Book _arg0;
                //并為其創(chuàng)建新的對象
                _arg0 = new com.tzx.aidlinout.aidl.Book();
                //獲取調(diào)用this.addOutBook方法返回的_result
                com.tzx.aidlinout.aidl.Book _result = this.addOutBook(_arg0);
                reply.writeNoException();
                //并向reply中寫入返回值_result
                if ((_result != null)) {
                    reply.writeInt(1);
                    _result.writeToParcel(reply,
                        android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                } else {
                    reply.writeInt(0);
                }
                //再將參數(shù)_arg0寫入reply中俯邓,至于為什么寫入,我們看看客戶端Proxy中的讀取
                if ((_arg0 != null)) {
                    reply.writeInt(1);
                    _arg0.writeToParcel(reply,
                        android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                } else {
                    reply.writeInt(0);
                }

                return true;
            }

            case TRANSACTION_addInoutBook: {
                data.enforceInterface(DESCRIPTOR);
                //聲明輸入的參數(shù)_arg0的引用
                com.tzx.aidlinout.aidl.Book _arg0;
                //并根據(jù)輸入的數(shù)據(jù)為其創(chuàng)建對象
                if ((0 != data.readInt())) {
                    _arg0 = com.tzx.aidlinout.aidl.Book.CREATOR.createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                //獲取調(diào)用this.addInoutBook方法返回的_result
                com.tzx.aidlinout.aidl.Book _result = this.addInoutBook(_arg0);
                reply.writeNoException();
                //并向reply中寫入返回值_result
                if ((_result != null)) {
                    reply.writeInt(1);
                    _result.writeToParcel(reply,
                        android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                } else {
                    reply.writeInt(0);
                }
                //再將參數(shù)_arg0寫入reply中谦纱,至于為什么寫入看成,我們看看客戶端Proxy中的讀取
                if ((_arg0 != null)) {
                    reply.writeInt(1);
                    _arg0.writeToParcel(reply,
                        android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                } else {
                    reply.writeInt(0);
                }

                return true;
            }

            case TRANSACTION_getBookList: {
                data.enforceInterface(DESCRIPTOR);

                java.util.List<com.tzx.aidlinout.aidl.Book> _result = this.getBookList();
                reply.writeNoException();
                reply.writeTypedList(_result);

                return true;
            }
            }

            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.tzx.aidlinout.aidl.IBookManager {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            @Override
            public com.tzx.aidlinout.aidl.Book addInBook(
                com.tzx.aidlinout.aidl.Book book)
                throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                com.tzx.aidlinout.aidl.Book _result;

                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    //將客戶端調(diào)用時傳入的參數(shù)寫入_data中
                    if ((book != null)) {
                        _data.writeInt(1);
                        book.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    //將_data、_reply序列化對象和Stub.TRANSACTION_addInBook指令傳遞到Server端
                    mRemote.transact(Stub.TRANSACTION_addInBook, _data, _reply,
                        0);
                    _reply.readException();
                    //讀取Server端返回的序列化_reply中的對象
                    if ((0 != _reply.readInt())) {
                        _result = com.tzx.aidlinout.aidl.Book.CREATOR.createFromParcel(_reply);
                    } else {
                        _result = null;
                    }
                    //然后直接將_result返回
                    //我們發(fā)現(xiàn)整個方法調(diào)用期間傳入的對象book只是將數(shù)據(jù)寫入到Server跨嘉,它的值進行并沒有任何修改川慌。
                    //總結(jié):in類型的參數(shù),它向服務(wù)端傳入數(shù)據(jù)祠乃,但是卻不接受Server返回的值梦重。
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }

                return _result;
            }

            @Override
            public com.tzx.aidlinout.aidl.Book addOutBook(
                com.tzx.aidlinout.aidl.Book book)
                throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                com.tzx.aidlinout.aidl.Book _result;

                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    //將_data、_reply序列化對象和Stub.TRANSACTION_addInBook指令傳遞到Server端
                    //_data和_reply序列化對象并沒有進行寫入
                    mRemote.transact(Stub.TRANSACTION_addOutBook, _data,
                        _reply, 0);
                    _reply.readException();
                    //讀取Server端返回的序列化_reply中的對象亮瓷,寫入到_result
                    if ((0 != _reply.readInt())) {
                        _result = com.tzx.aidlinout.aidl.Book.CREATOR.createFromParcel(_reply);
                    } else {
                        _result = null;
                    }
                    //讀取Server端返回的序列化_reply中的對象琴拧,寫入到傳入的book對象中
                    if ((0 != _reply.readInt())) {
                        book.readFromParcel(_reply);
                    }
                    //然后直接將_result返回
                    //我們發(fā)現(xiàn)整個方法調(diào)用期間傳入的對象book并沒有將數(shù)據(jù)寫入到Server,它的值確實是Server返回的嘱支。
                    //總結(jié):out類型的參數(shù)蚓胸,它并不向服務(wù)端傳入數(shù)據(jù)挣饥,但是卻接受Server返回的值。
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }

                return _result;
            }

            @Override
            public com.tzx.aidlinout.aidl.Book addInoutBook(
                com.tzx.aidlinout.aidl.Book book)
                throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                com.tzx.aidlinout.aidl.Book _result;

                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    //將客戶端調(diào)用時傳入的參數(shù)寫入_data中
                    if ((book != null)) {
                        _data.writeInt(1);
                        book.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    //將_data沛膳、_reply序列化對象和Stub.TRANSACTION_addInoutBook指令傳遞到Server端
                    mRemote.transact(Stub.TRANSACTION_addInoutBook, _data,
                        _reply, 0);
                    _reply.readException();
                    //讀取Server端返回的序列化_reply中的對象扔枫,寫入到_result
                    if ((0 != _reply.readInt())) {
                        _result = com.tzx.aidlinout.aidl.Book.CREATOR.createFromParcel(_reply);
                    } else {
                        _result = null;
                    }
                    //讀取Server端返回的序列化_reply中的對象,寫入到傳入的book對象中
                    if ((0 != _reply.readInt())) {
                        book.readFromParcel(_reply);
                    }
                    //然后直接將_result返回
                    //我們發(fā)現(xiàn)整個方法調(diào)用期間傳入的對象book將其數(shù)據(jù)寫入到Server锹安,并且它的值被Server返回的數(shù)據(jù)修改短荐。
                    //總結(jié):inout類型的參數(shù),它既向服務(wù)端傳入數(shù)據(jù)叹哭,也卻接受Server返回的值忍宋。
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }

                return _result;
            }

            @Override
            public java.util.List<com.tzx.aidlinout.aidl.Book> getBookList()
                throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.tzx.aidlinout.aidl.Book> _result;

                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getBookList, _data,
                        _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.tzx.aidlinout.aidl.Book.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }

                return _result;
            }
        }
    }
}

看了這么多代碼是不是感覺腦袋大了,沒事接下來一張圖幫你理的清清楚楚的:


aidl-tag-type

經(jīng)過兩篇文章對aidl的講解风罩,我想你已經(jīng)把它理解的透透的了糠排,如果還有什么問題可以給我留言哦~!

GitHubDemo地址

想閱讀作者的更多文章泊交,可以查看我 個人博客 和公共號:

振興書城

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乳讥,一起剝皮案震驚了整個濱河市柱查,隨后出現(xiàn)的幾起案子廓俭,更是在濱河造成了極大的恐慌,老刑警劉巖唉工,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件研乒,死亡現(xiàn)場離奇詭異,居然都是意外死亡淋硝,警方通過查閱死者的電腦和手機雹熬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谣膳,“玉大人竿报,你說我怎么就攤上這事〖萄瑁” “怎么了烈菌?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長花履。 經(jīng)常有香客問我芽世,道長,這世上最難降的妖魔是什么诡壁? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任济瓢,我火速辦了婚禮,結(jié)果婚禮上妹卿,老公的妹妹穿的比我還像新娘旺矾。我一直安慰自己蔑鹦,他們只是感情好,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布箕宙。 她就那樣靜靜地躺著举反,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扒吁。 梳的紋絲不亂的頭發(fā)上火鼻,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機與錄音雕崩,去河邊找鬼魁索。 笑死,一個胖子當著我的面吹牛盼铁,可吹牛的內(nèi)容都是我干的粗蔚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼饶火,長吁一口氣:“原來是場噩夢啊……” “哼鹏控!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起肤寝,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤当辐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鲤看,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缘揪,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年义桂,在試婚紗的時候發(fā)現(xiàn)自己被綠了找筝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡慷吊,死狀恐怖袖裕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情溉瓶,我是刑警寧澤急鳄,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站嚷闭,受9級特大地震影響攒岛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜胞锰,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一灾锯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嗅榕,春花似錦顺饮、人聲如沸吵聪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吟逝。三九已至,卻和暖如春赦肋,著一層夾襖步出監(jiān)牢的瞬間块攒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工佃乘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留囱井,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓趣避,卻偏偏與公主長得像庞呕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子程帕,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

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