Android Handler使用方法

目錄:


目錄

1. 前言

本篇文章介紹 Android Handler 的基本使用方法,且 Demo 會以 Java & Kotlin 兩種代碼形式進(jìn)行展示。
在 Android 實際開發(fā)中,我們經(jīng)常會遇到耗時任務(wù),比如:網(wǎng)絡(luò)請求API接口來獲取數(shù)據(jù)、數(shù)據(jù)庫 CRUD 操作等等,我們需要額外創(chuàng)建開啟工作線程來處理這些耗時任務(wù)。由于 Android 規(guī)定只能由主線程才能處理 UI 工作,所以這時候我們就需要通過 Handler 來通知主線程處理 UI 工作。

1.1 定義

Handler:子線程與主線程之間的溝通中介,用于傳遞處理消息。

在 Android 中,為保證處理 UI 工作的線程穩(wěn)定安全,規(guī)定只有主線程才能更新處理 UI 工作。所以當(dāng)子線程想處理 UI 工作時,就需要通過 Handler 來通知主線程作出相對應(yīng)的 UI 處理工作。
如下圖所示:

Handler是子線程與主線程的溝通中介

本篇文章,我將介紹 Handler 的三種使用方法,分別是:

  1. Handler.sendMessage(Message)
  2. Handler.post(Runnable)
  3. Handler.obtainMessage(what).sendToTarget();

2. Handler.sendMessage()方法

Handler.sendMessage(Msg) 方法是最為常見的一種方法。

2.1 使用步驟說明

其使用步驟分四步,如下所示:

  1. 步驟一:新建 Handler 對象,覆寫 handleMessage(Message) 方法。
  2. 步驟二:新建 Message 對象,設(shè)置其攜帶的數(shù)據(jù)。
  3. 步驟三:在子線程中通過 Handler.sendMessage(Message) 方法發(fā)送信息。
  4. 步驟四:在 Handler 的 handleMessage(Message msg) 方法中處理消息,通知主線程作出相對應(yīng)的 UI 工作。
  • 步驟一:新建 Handler 對象,覆寫 handleMessage(Message) 方法
//創(chuàng)建 Handler對象,并關(guān)聯(lián)主線程消息隊列
mHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
            ···略···
        }
    }
};
  • 步驟二:新建 Message 對象,設(shè)置其攜帶的數(shù)據(jù)
Bundle bundle = new Bundle();
bundle.putInt(CURRENT_PROCESS_KEY, i);
Message msg = new Message();
msg.setData(bundle);
msg.what = 2;
  • 步驟三:在子線程中通過 Handler.sendMessage(Message) 方法發(fā)送信息
mHandler.sendMessage(msg)
  • 步驟四:在 Handler 的 handleMessage(Message msg) 方法中處理消息,通知主線程作出相對應(yīng)的 UI 工作
mHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        //根據(jù)信息編碼及數(shù)據(jù)做出相對應(yīng)的處理
        switch (msg.what) {
            case 1:
                //更新 TextView UI
                mDisplayTv.setText("CustomChildThread starting!");
                break;
            case 2:
                //獲取 ProgressBar 的進(jìn)度,然后顯示進(jìn)度值
                Bundle bundle = msg.getData();
                int process = bundle.getInt(CURRENT_PROCESS_KEY);
                mProgressBar.setProgress(process);
                break;
            default:
                break;
        }
    }
};

2.2 具體例子

根據(jù)上述的使用步驟,我們來完成一個完整的例子:
新建一個線程,模擬處理耗時任務(wù),然后將處理進(jìn)度通過 ProgressBar 顯示出來。
效果如下所示:點(diǎn)擊按鈕,開啟線程處理耗時操作。

Handler.sendMessage() Demo

具體代碼見下:

2.2.1 Java版本Demo

Java版本的具體代碼如下所示:

public class HandlerAddThreadActivity extends AppCompatActivity {
    public static final String CURRENT_PROCESS_KEY = "CURRENT_PROCESS";
    private TextView mDisplayTv;
    private Handler mHandler;
    private ProgressBar mProgressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_add_thread);

        TextView titleTv = findViewById(R.id.title_tv);
        titleTv.setText("Handler + Thread");
        
        mDisplayTv = findViewById(R.id.display_tv);
        mProgressBar = findViewById(R.id.test_handler_progress_bar);

        //mHandler用于處理主線程消息隊列中的子線程消息
        mHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case 1:
                        //更新 TextView UI
                        mDisplayTv.setText("CustomChildThread starting!");
                        break;
                    case 2:
                        //獲取 ProgressBar 的進(jìn)度,然后顯示進(jìn)度值
                        Bundle bundle = msg.getData();
                        int process = bundle.getInt(CURRENT_PROCESS_KEY);
                        mProgressBar.setProgress(process);
                        break;
                    default:
                        break;
                }

            }
        };
        
        Button mClickBtn = findViewById(R.id.click_btn);
        mClickBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //開啟子線程,子線程處理UI工作
                CustomChildThread customThread = new CustomChildThread();
                customThread.start();
            }
        });
    }

    /**
     * 子線程,用于處理耗時工作
     */
    public class CustomChildThread extends Thread {

        @Override
        public void run() {
            //在子線程中創(chuàng)建一個消息對象
            Message childThreadMessage = new Message();
            childThreadMessage.what = 1;
            //將該消息放入主線程的消息隊列中
            mHandler.sendMessage(childThreadMessage);

            //模擬耗時進(jìn)度,將進(jìn)度值傳給主線程用于更新 ProgressBar 進(jìn)度。
            for (int i = 1; i <= 5; i++) {
                try {
                    //讓當(dāng)前執(zhí)行的線程(即 CustomChildThread)睡眠 1s
                    Thread.sleep(1000);

                    //Message 傳遞參數(shù)
                    Bundle bundle = new Bundle();
                    bundle.putInt(CURRENT_PROCESS_KEY, i);
                    Message progressBarProcessMsg = new Message();
                    progressBarProcessMsg.setData(bundle);
                    progressBarProcessMsg.what = 2;
                    mHandler.sendMessage(progressBarProcessMsg);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

執(zhí)行結(jié)果看上圖 Handler.sendMessage() Demo

2.2.2 Kotlin版本Demo

Kotlin版本的代碼如下所示:

class TestThreadAddHandlerActivity : AppCompatActivity() {
    companion object {
        const val PROGRESS_VALUE_KEY = "PROGRESS_VALUE"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_thread_add_handler)

        handlerAddThreadStartBtn.setOnClickListener(View.OnClickListener {
            //工作線程開始模擬下載任務(wù)
            val workThread: WorkThread = WorkThread(this)
            workThread.start()
        })
    }

    class WorkThread(activity: TestThreadAddHandlerActivity) : Thread() {
        private var handler: MyHandler = MyHandler(activity)

        override fun run() {
            super.run()
            for (i in 0..6) {
                sleep(1000)
                //通過 Handler 將進(jìn)度參數(shù)傳遞給 主線程,讓其更新 progressBar 進(jìn)度
                val message = Message()
                message.what = 1
                val bundle = Bundle()
                bundle.putInt(PROGRESS_VALUE_KEY, i)
                message.data = bundle
                handler.sendMessage(message)
            }
        }
    }

    /**
     * 靜態(tài)內(nèi)部類,防止內(nèi)存泄漏
     */
    class MyHandler(activity: TestThreadAddHandlerActivity) : Handler() {
        private var weakReference = WeakReference(activity)

        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            //處理消息
            when (msg.what) {
                1 -> {
                    val activity = weakReference.get()
                    if (activity != null && !activity.isFinishing) {
                        //獲取消息中攜帶的任務(wù)處理進(jìn)度參數(shù),然后設(shè)置成 ProgressBar 的進(jìn)度。
                        val progressValue: Int = msg.data.get(PROGRESS_VALUE_KEY) as Int
                        activity.handlerAddThreadProgressBar.progress = progressValue
                    }
                }
            }
        }
    }
}

執(zhí)行結(jié)果看上圖 Handler.sendMessage() Demo

3. Handler.post()方法

除了使用 Handler.sendMessage(Message) 來發(fā)送信息,Handler 還支持 post(Runnable) 方法來傳遞消息,通知主線程做出相對應(yīng)的 UI 工作。使用方法如下:

/**
 * 將可運(yùn)行的 Runnable 添加到消息隊列。Runnable 將在該 Handler 相關(guān)的線程上運(yùn)行處理。
 * The runnable will be run on the thread to which this handler is attached.
 */
new Handler().post(new Runnable() {
    @Override
    public void run() {
        //更新處理 UI 工作
    }
});

3.1 具體例子

實現(xiàn)上述同樣的功能 -> 點(diǎn)擊按鈕,子線程開始工作模擬處理耗時任務(wù),通過 Handler 將進(jìn)度告訴主線程,再通過 ProgressBar 將進(jìn)度顯示出來。
效果如下:

Handler.post() Demo

具體代碼見下:

3.1.1 Java版本Demo

Java版本的具體代碼如下:

public class HandlerPostFunctionActivity extends AppCompatActivity {
    private Handler mMainHandler;
    private ProgressBar mProgressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_add_thread);

        TextView titleTv = findViewById(R.id.title_tv);
        titleTv.setText("Handler post() function");

        mProgressBar = findViewById(R.id.test_handler_progress_bar);

        //新建靜態(tài)內(nèi)部類 Handler 對象
        mMainHandler = new Handler(getMainLooper());

        Button mClickBtn = findViewById(R.id.click_btn);
        mClickBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //開啟子線程,子線程處理UI工作
                CustomChildThread customThread = new CustomChildThread();
                customThread.start();
            }
        });
    }

    /**
     * 子線程,用于處理耗時工作
     */
    public class CustomChildThread extends Thread {

        @Override
        public void run() {
            //模擬耗時進(jìn)度,將進(jìn)度值傳給主線程用于更新 ProgressBar 進(jìn)度。
            for (int i = 1; i <= 5; i++) {
                try {
                    //讓當(dāng)前執(zhí)行的線程(即 CustomChildThread)睡眠 1s
                    Thread.sleep(1000);

                    //新創(chuàng)建一個 Runnable 用戶處理 UI 工作
                    MyRunnable runnable = new MyRunnable(HandlerPostFunctionActivity.this, i);
                    //調(diào)用Handler post 方法。
                    mMainHandler.post(runnable);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 將 Runnable 寫成靜態(tài)內(nèi)部類,防止內(nèi)存泄露
     */
    public static class MyRunnable implements Runnable {
        private int progressBarValue;
        private WeakReference<HandlerPostFunctionActivity> weakReference;

        MyRunnable(HandlerPostFunctionActivity activity, int value) {
            this.weakReference = new WeakReference<>(activity);
            this.progressBarValue = value;
        }

        @Override
        public void run() {
            HandlerPostFunctionActivity activity = weakReference.get();
            if (activity != null && !activity.isFinishing()) {
                activity.mProgressBar.setProgress(progressBarValue);
            }
        }
    }
}

執(zhí)行結(jié)果看上圖 Handler.post() Demo

3.1.2 Kotlin版本Demo

Kotlin版本的具體代碼如下:

class TestHandlerPostRunnableActivity : AppCompatActivity() {
    private var mMainHandler: Handler? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_thread_add_handler)

        handlerAddThreadStartBtn.setOnClickListener(View.OnClickListener {
            //工作線程開始模擬下載任務(wù)
            val workThread: WorkThread = WorkThread(this)
            workThread.start()
        })

        //創(chuàng)建 Handler,關(guān)聯(lián)App的 主Looper 對象
        mMainHandler = Handler(Looper.getMainLooper())
    }

    class WorkThread(private var activity: TestHandlerPostRunnableActivity) : Thread() {
        private var handler: Handler? = activity.mMainHandler

        override fun run() {
            super.run()
            for (i in 0..6) {
                sleep(1000)
                //新建 Runnable 設(shè)置進(jìn)度參數(shù)傳,然后通過 post(Runnable) 方法,讓其更新 progressBar 進(jìn)度
                val runnable: MyRunnable = MyRunnable(activity, i)
                handler?.post(runnable)
            }
        }
    }

    /**
     * 處理 UI 工作。
     * 靜態(tài)內(nèi)部類,防止內(nèi)存泄露
     */
    class MyRunnable(activity: TestHandlerPostRunnableActivity, value: Int) : Runnable {
        private var weakReference = WeakReference(activity)
        private var progressValue = value

        override fun run() {
            val activity = weakReference.get()
            if (activity != null && !activity.isFinishing) {
                //獲取任務(wù)執(zhí)行進(jìn)度參數(shù),更新 progressBar 進(jìn)度
                activity.handlerAddThreadProgressBar.progress = progressValue
            }
        }
    }
}

執(zhí)行結(jié)果看上圖 Handler.post() Demo

4. obtainMessage()方法

obtainMessage() 方法與 sendMessage() 方法很相似,通過 mHandler.obtainMessage().sendToTarget() 發(fā)送信息。該方法與 sendMessage() 的區(qū)別就是你不用額外去創(chuàng)建一個 Message 對象。

obtainMessage() 方法有三種,分別是:

//指定 what 用于區(qū)分,通過 Message.what 獲得
public final Message obtainMessage(int what);

//傳遞obj參數(shù),通過 Message.obj 獲得
public final Message obtainMessage(int what, @Nullable Object obj)

//傳遞arg1 arg2參數(shù),通過 Message.arg1 Message.arg2 獲得
public final Message obtainMessage(int what, int arg1, int arg2)

4.1 具體例子

同樣實現(xiàn)上述同樣的功能 -> 點(diǎn)擊按鈕,子線程開始工作,通過 Handler 將進(jìn)度告訴主線程,通過 ProgressBar 將進(jìn)度顯示出來。
效果如下:

Handler.obtainMessage() Demo

具體代碼如下:

4.1.1 Java版本Demo

Java版本的具體代碼如下:

public class HandlerObtainMessageActivity extends AppCompatActivity {
    private TextView mDisplayTv;
    private Handler mHandler;
    private ProgressBar mProgressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_add_thread);

        TextView titleTv = findViewById(R.id.title_tv);
        titleTv.setText("Handler + Thread");

        mDisplayTv = findViewById(R.id.display_tv);
        mProgressBar = findViewById(R.id.test_handler_progress_bar);

        //mHandler用于處理主線程消息隊列中的子線程消息
        mHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case 1:
                        //更新 TextView UI
                        mDisplayTv.setText("Handler obtainMessage() Test!!");
                        break;
                    case 2:
                        //通過 msg.obj 獲取 ProgressBar 的進(jìn)度,然后顯示進(jìn)度值
                        int process = (int) msg.obj;
                        mProgressBar.setProgress(process);
                        break;
                    default:
                        break;
                }

            }
        };

        Button mClickBtn = findViewById(R.id.click_btn);
        mClickBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //開啟子線程,子線程處理UI工作
                CustomChildThread customThread = new CustomChildThread();
                customThread.start();
            }
        });
    }

    /**
     * 子線程,用于處理耗時工作
     */
    public class CustomChildThread extends Thread {

        @Override
        public void run() {
            //發(fā)送第一條消息,代表開始執(zhí)行異步任務(wù)
            mHandler.obtainMessage(1).sendToTarget();

            //模擬耗時進(jìn)度,將進(jìn)度值傳給主線程用于更新 ProgressBar 進(jìn)度。
            for (int i = 1; i <= 5; i++) {
                try {
                    //讓當(dāng)前執(zhí)行的線程(即 CustomChildThread)睡眠 1s
                    Thread.sleep(1000);

                    //將執(zhí)行進(jìn)度參數(shù) i 傳遞給主線程 progressBar
                    mHandler.obtainMessage(2, i).sendToTarget();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }


        }
    }

}

執(zhí)行結(jié)果看上圖 Handler.obtainMessage() Demo

4.1.2 kotlin版本Demo

Kotlin版本的具體代碼如下:

class TestHandlerObtainMessageActivity : AppCompatActivity() {
    companion object {
        const val PROGRESS_VALUE_KEY = "PROGRESS_VALUE"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_thread_add_handler)

        handlerAddThreadStartBtn.setOnClickListener(View.OnClickListener {
            //工作線程開始模擬下載任務(wù)
            val workThread: WorkThread = WorkThread(this)
            workThread.start()
        })
    }

    class WorkThread(activity: TestHandlerObtainMessageActivity) : Thread() {
        private var handler: MyHandler = MyHandler(activity)

        override fun run() {
            super.run()
            for (i in 0..6) {
                sleep(1000)
                //通過 Handler 將進(jìn)度參數(shù)傳遞給 主線程,讓其更新 progressBar 進(jìn)度
                val bundle = Bundle()
                bundle.putInt(PROGRESS_VALUE_KEY, i)
                handler.obtainMessage(1, bundle).sendToTarget()
            }
        }
    }

    /**
     * 靜態(tài)內(nèi)部類,防止內(nèi)存泄漏
     */
    class MyHandler(activity: TestHandlerObtainMessageActivity) : Handler() {
        private var weakReference = WeakReference(activity)

        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            when (msg.what) {
                1 -> {
                    val activity = weakReference.get()
                    if (activity != null && !activity.isFinishing) {
                        //獲取任務(wù)執(zhí)行進(jìn)度參數(shù),然后通過 ProgressBar 顯示出來
                        val bundle: Bundle = msg.obj as Bundle
                        val progressValue: Int = bundle.get(PROGRESS_VALUE_KEY) as Int
                        activity.handlerAddThreadProgressBar.progress = progressValue
                    }
                }
            }
        }
    }
}

執(zhí)行結(jié)果看上圖 Handler.obtainMessage() Demo

5. 總結(jié):

在實際開發(fā)中,三種方法的使用都可行,具體用哪種方法,需結(jié)合你的實際情況及個人喜好。另外,在實際使用中往往將 Handler 寫成靜態(tài)內(nèi)部類,這時需要注意防止內(nèi)存泄露!(The handler class should be static or leaks might occur),具體代碼見上方!

5.1 在子線程中創(chuàng)建Handler

思考: 在上面代碼中, 我們都是在主線程中創(chuàng)建了 Handler 對象,那如果在子線程中創(chuàng)建一個 Handler 對象呢?會發(fā)生什么呢?
如下所示:我們在 CustomChildThread 線程中,新建一個 Handler 對象。

public class CustomChildThread extends Thread {
    @Override
    public void run() {
        Handler handler = new Handler(Activity.this);
        //會報錯:java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    }
}

結(jié)果: 拋出異常: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()。
原因: 因為在創(chuàng)建 Handler對象時要關(guān)聯(lián)所處線程的 Looper對象,而我們的子線程沒有 Looper,所以會拋出上述異常。
解決方法: 通過調(diào)用,Looper.prepare() 方法為子線程創(chuàng)建一個 Looper 對象,并且調(diào)用 Looper.loop() 方法開始消息循環(huán)。如下所示:

class CustomChildThread extends Thread {
    @Override
    public void run() {
        //為當(dāng)前線程創(chuàng)建一個 Looper 對象
        Looper.prepare();
        
        //在子線程中創(chuàng)建一個 Handler 對象
        Handler handler = new Handler() {
            public void handleMessage(Message msg) {
                // 在這里處理傳入的消息
            }
        };
        //開始消息循環(huán)
        Looper.loop();
    }
}

至此關(guān)于 Handler 的使用方法也就介紹完畢了,如果你想深入學(xué)習(xí) Handler,了解其通信機(jī)制以及源碼分析,請看博客 Android Handler深入學(xué)習(xí)(源碼分析)

其實分享文章的最大目的正是等待著有人指出我的錯誤,如果你發(fā)現(xiàn)哪里有錯誤,請毫無保留的指出即可,虛心請教。

另外,如果你覺得文章不錯,對你有所幫助,請給我點(diǎn)個贊,就當(dāng)鼓勵,謝謝~Peace~!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,237評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,957評論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,248評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,356評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,081評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,485評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,534評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,720評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,263評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,025評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,204評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,787評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,461評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,874評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,105評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,945評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,205評論 2 375

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