【Android】Service完全解析之必知必會(huì)

想必對(duì)于Android開發(fā)者來(lái)說(shuō),對(duì)Service一定不陌生了阵面,作為大名鼎鼎的四大組件之一的service,在Android中有著不可替代的作用,它不像Activity那么光鮮亮麗才沧,一般都是默默躲在后臺(tái)執(zhí)行著一些“見不得人的”任務(wù),比如下載文件绍刮,音樂播放等等糜工,即使退出應(yīng)用了,它還是很頑強(qiáng)的在后臺(tái)運(yùn)行著录淡,雖然隨著android版本的不斷提高捌木,安全性的要求也越來(lái)越高,Service的一些黑科技也變得越來(lái)越難嫉戚。

最近在學(xué)習(xí)Service刨裆,做個(gè)記錄,希望能給您一些幫助彬檀,我們都知道service有兩種啟動(dòng)方式帆啃,分別是startService和bindService,它們有各自的生命周期方法窍帝,盜張官網(wǎng)的圖:

生命周期

下面分別來(lái)看下它的使用吧努潘,我們先創(chuàng)建一個(gè)Service:

public class MyService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e("wangkeke","------onBind");
        return new MyBinder();
    }

    public interface MyIBinder{
        void showGetMyService();
    }

    public class MyBinder extends Binder implements MyIBinder{

        public void stopService(ServiceConnection serviceConnection){
            unbindService(serviceConnection);
        }

        @Override
        public void showGetMyService() {
            Log.e("wangkeke","------獲取遠(yuǎn)程服務(wù)");
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e("wangkeke","------onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("wangkeke","------onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e("wangkeke","------onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e("wangkeke","------onDestroy");
    }
}

我們簡(jiǎn)單定義了一個(gè)MyService,重寫了幾個(gè)比較重要的方法,別忘了在AndroidManifest.xml里面注冊(cè):

<service android:name=".MyService"/>

1.startService

然后在Activity里我們先通過(guò)startService來(lái)啟動(dòng)它:

Intent intent = new Intent(MainActivity.this,MyService.class);
startService(intent);

很簡(jiǎn)單傳遞給它一個(gè)intent疯坤,指定要啟動(dòng)的Service就可以了报慕,運(yùn)行看看結(jié)果:


第一次啟動(dòng)

執(zhí)行了onCreate,onStartCommand压怠,那么如果我們多次startService呢眠冈?看看效果:


多次執(zhí)行startService

可以看出只有第一次執(zhí)行才會(huì)調(diào)用onCreate,之后只會(huì)調(diào)用onStartCommand方法菌瘫,啟動(dòng)是成功了蜗顽,但我們?cè)撊绾瓮V筍ervcie呢?一種方式是在自定義的Service中使用stopSelf()停止自己雨让,另一種是在外部通過(guò)stopService(intent)的方式停止服務(wù)雇盖。
現(xiàn)在我們調(diào)用如下停止服務(wù)的代碼:
Intent intent = new Intent(MainActivity.this,MyService.class);
stopService(intent);

看控制臺(tái)打印日志:


停止服務(wù)

停止服務(wù)只會(huì)調(diào)用onDestory方法,多次調(diào)用stopService時(shí)栖忠,onDestory只會(huì)調(diào)用一次刊懈,這個(gè)也很好理解,比較服務(wù)都不在了娃闲,調(diào)用也就無(wú)效了虚汛。

startService適用于執(zhí)行后臺(tái)任務(wù),但是要注意service默認(rèn)是在主線程執(zhí)行的皇帮,執(zhí)行耗時(shí)操作的話請(qǐng)務(wù)必開啟子線程去處理卷哩。

2.bindService

下面我們換種方式啟動(dòng)Service,通過(guò)bindService的方式属拾,bindService方法需要三個(gè)參數(shù):

    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);
    }

service就是我們的intent将谊,ServiceConnection是個(gè)接口,當(dāng)我們bindservice之后渐白,AMS會(huì)回調(diào)ServiceConnection接口對(duì)象的onServiceConnected()方法尊浓,onServiceConnected方法會(huì)把遠(yuǎn)端service的代理binder傳遞過(guò)來(lái),這樣就可以通過(guò)這個(gè)代理binder跨進(jìn)程調(diào)用service中的方法了纯衍。
我們先創(chuàng)建一個(gè)ServiceConnection對(duì)象:

    public ServiceConnection conn =  new ServiceConnection(){
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e("wangkeke","-------onServiceConnected");
            serviceIsConnected = true;
            MyService.MyBinder myBinder = (MyService.MyBinder) service;
            myBinder.showGetMyService();

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e("wangkeke","-------onServiceDisconnected");
            serviceIsConnected = false;
        }
    };

然后通過(guò)bindService啟動(dòng)它:

Intent intent = new Intent(MainActivity.this,MyService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);

運(yùn)行結(jié)果如下:


第一次運(yùn)行bindService

依次調(diào)用了onCreate栋齿,onBind,之后遠(yuǎn)程服務(wù)連接成功襟诸,調(diào)用了onServiceConnected瓦堵,可以看到所有的回調(diào)都在主線程,當(dāng)服務(wù)連接成功后歌亲,通過(guò)onServiceConnected拿到IBinder對(duì)象菇用,就可以調(diào)用遠(yuǎn)程service的方法了。

bindService的第三個(gè)參數(shù)的含義:bindservice在建立連接時(shí)陷揪,如果發(fā)現(xiàn)service還沒啟動(dòng)惋鸥,會(huì)根據(jù)flag是否設(shè)置BIND_AUTO_CREATE杂穷,決定是否啟動(dòng)這個(gè)service。

那么綁定后的service如何解綁呢卦绣,通過(guò)unbindService方法耐量,傳入綁定service時(shí)所創(chuàng)建的ServiceConnection對(duì)象即可:

unbindService(conn);

生命周期打印如下:


unbindService

ServiceConnection接口的onServiceDisconnected()方法并不會(huì)在unbindService()操作斷開邏輯連接時(shí)執(zhí)行。而是在遠(yuǎn)端service進(jìn)程終止時(shí)迎卤,AMS才會(huì)回調(diào)onServiceDisconnected()。

上面的例子玷坠,在onBind方法中蜗搔,我們返回了new MyBinder(),如果我們直接返回null的話八堡,就不會(huì)回調(diào)ServiceConnection的onServiceConnected方法了樟凄。

注意:bindservice是和組件綁定的,依賴于組件而存在兄渺,所以在頁(yè)面退出的時(shí)候一定要調(diào)用unbindService解綁缝龄,不然會(huì)拋出異常,而startService則不受啟動(dòng)服務(wù)組件的影響挂谍,可以繼續(xù)在后臺(tái)繼續(xù)執(zhí)行叔壤。

另外要注意,服務(wù)是在主線程中運(yùn)行的口叙,如果要進(jìn)行網(wǎng)絡(luò)操作炼绘,音樂播放等CPU密集型工作或者阻塞性操作,請(qǐng)開啟新線程來(lái)處理妄田。

3.startService之后調(diào)用bindService

現(xiàn)在我們看這么一種情況俺亮,我們startService之后調(diào)用bindService,看看運(yùn)行結(jié)果:

先點(diǎn)擊startService疟呐,再點(diǎn)擊bindService

可以看到當(dāng)bindService已經(jīng)啟動(dòng)的服務(wù)時(shí)脚曾,依然可以bind成功,只是不會(huì)重新調(diào)用onCreate方法启具,接著我們調(diào)用stopService看看本讥,咦,點(diǎn)擊之后并沒有回調(diào)onDestory鲁冯,看來(lái)僅僅通過(guò)
stopService是無(wú)法停止服務(wù)了囤踩,因?yàn)樗推渌M件還綁定著呢,現(xiàn)在調(diào)下unbindService試試:


unbindService

unBindService之后晓褪,服務(wù)才會(huì)銷毀堵漱,所以說(shuō)如果同時(shí)使用了start和bind啟動(dòng)服務(wù),必須要stopservice和unbindservice都執(zhí)行后服務(wù)才會(huì)銷毀涣仿。
至于先bind再start也是同樣的道理勤庐,服務(wù)的創(chuàng)建onCreate方法只會(huì)調(diào)用一次示惊,銷毀同樣需要調(diào)用stopservice和unbindservice后才能成功,具體大家可以自己實(shí)驗(yàn)感受下愉镰。

4.Service模擬下載任務(wù)

我們來(lái)模擬一個(gè)下載任務(wù)米罚,具體代碼如下:

public class DownloadService extends Service {

    private ServiceHandler serviceHandler;
    private NotificationManager mNotificationManager;

    private final class ServiceHandler extends Handler{

        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            //開始處理耗時(shí)任務(wù)
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Toast.makeText(DownloadService.this, "下載任務(wù)完成···", Toast.LENGTH_SHORT).show();
            mNotificationManager.cancel(100);
            //任務(wù)執(zhí)行完畢,根據(jù)startId停止服務(wù)
            stopSelf(msg.arg1);
        }
    }

    @Override
    public void onCreate() {
        HandlerThread thread = new HandlerThread("downloadTest", Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();

        serviceHandler = new ServiceHandler(thread.getLooper());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Toast.makeText(this, "開始任務(wù)···", Toast.LENGTH_SHORT).show();

        Message msg = Message.obtain();
        msg.arg1 = startId;
        serviceHandler.sendMessage(msg);
        showNotifycation();
        return super.onStartCommand(intent, flags, startId);
    }

    private void showNotifycation(){
        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(this,"downloadfile")
                        .setSmallIcon(R.mipmap.ic_launcher)
                        .setContentTitle("溫馨提醒")
                        .setContentText("當(dāng)前正在下載中···");
        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(100, mBuilder.build());
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

我們?cè)趏nCreate中創(chuàng)建了HandlerThread丈探,開啟消息循環(huán)录择,然后創(chuàng)建了Handler用來(lái)處理耗時(shí)任務(wù),此時(shí)Handler取的是HandlerThread的Looper碗降,運(yùn)行在子線程中隘竭,在onStartCommand中我們發(fā)送了message并顯示了個(gè)通知,任務(wù)sleep 5秒后結(jié)束讼渊,關(guān)閉通知并停止服務(wù)动看。運(yùn)行效果如下:


模擬耗時(shí)任務(wù)

5.onStartCommand的返回值

Service作為一個(gè)組件,很難保證一直存在爪幻,當(dāng)service進(jìn)程被kill掉的時(shí)候菱皆,service會(huì)如何響應(yīng)呢?onStartCommand的返回值其實(shí)就是對(duì)應(yīng)的響應(yīng)策略:

  1. START_STICKY:service進(jìn)程被kill掉后挨稿,會(huì)重新創(chuàng)建service仇轻,并且調(diào)用onStartCommand(Intent,int,int)方法,但I(xiàn)ntent將為null奶甘。

2.START_NOT_STICKY:如果在執(zhí)行完onStartCommand后拯田,服務(wù)被異常kill掉,系統(tǒng)不會(huì)自動(dòng)重啟該服務(wù)甩十。

3.START_REDELIVER_INTENT:如果在執(zhí)行完onStartCommand后船庇,服務(wù)被異常kill掉,系統(tǒng)會(huì)自動(dòng)重啟該服務(wù)侣监,并將Intent的值傳入鸭轮。

4.START_STICKY_COMPATIBILITY:兼容低版本,與 START_STICKY 作用相同橄霉,但不保證每次都能重啟成功窃爷。

6.啟動(dòng)activity和彈出dialog

我們可能在某個(gè)合適的時(shí)機(jī)需要在Service里彈出Dialog,來(lái)測(cè)試下姓蜂,我們啟動(dòng)服務(wù)5秒后彈出dialog按厘,代碼如下:

public class DialogService extends Service {

    private ServiceHandler serviceHandler;
    private NotificationManager mNotificationManager;

    private final class ServiceHandler extends Handler{

        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            //彈出dialog
            showDialog();
        }
    }

    private void showDialog() {

        AlertDialog.Builder dialog = new AlertDialog.Builder(this);

        dialog.setTitle("我是Service里的彈窗")
                .setIcon(R.mipmap.ic_launcher)
                .setMessage("沒想到吧!钱慢!")
                .setPositiveButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(DialogService.this, "點(diǎn)擊了取消", Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
                    }
                }).setNegativeButton("確定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(DialogService.this, "點(diǎn)擊了確定", Toast.LENGTH_SHORT).show();
                dialog.dismiss();
            }
        }).create().show();

    }

    @Override
    public void onCreate() {
        serviceHandler = new ServiceHandler(Looper.getMainLooper());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, final int startId) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Message msg = Message.obtain();
                msg.arg1 = startId;
                serviceHandler.sendMessage(msg);
            }
        }).start();


        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

然后運(yùn)行后逮京,5秒后,果然········崩潰了束莫,異常如下:


彈出dialog崩潰

好吧懒棉,既然要主題那就給你設(shè)置個(gè):

    <style name="myDialogTheme" parent="Theme.AppCompat.Light.Dialog">
        <!--設(shè)置按鈕顏色-->
        <item name="colorAccent">@color/brand_accent</item>
        <!--設(shè)置背景顏色-->
        <item name="android:windowBackground">@color/white</item>
    </style>

    AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this,R.style.myDialogTheme);

再次運(yùn)行:


繼續(xù)崩潰

崩潰也很正常草描,咱們想脫離activity彈出dialog肯定不是那么簡(jiǎn)單,經(jīng)過(guò)一番調(diào)研搜索策严,要想彈出系統(tǒng)級(jí)別的dialog需要設(shè)置dialog的窗口類型為TYPE_SYSTEM_ALERT穗慕,提高dialog的窗口等級(jí),我們添加如下代碼再次嘗試:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//8.0新特性
      diaclog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY - 1);
} else {
      diaclog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
}

記得添加權(quán)限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

運(yùn)行后妻导,終于成功彈出dialog逛绵,啟動(dòng)服務(wù)后5秒鐘彈出dialog,效果如下:


彈出全局dialog

當(dāng)然在Service中彈出Dialog也可以通過(guò)啟動(dòng)透明Activity的方式倔韭,在Activity上彈出Dialog术浪,這里就不具體實(shí)現(xiàn)了,有興趣的同學(xué)可以自己實(shí)現(xiàn)感受下狐肢。

至于在Service中啟動(dòng)Activity就很簡(jiǎn)單了添吗,只需要注意要設(shè)置flag為FLAG_ACTIVITY_NEW_TASK沥曹,即在新的任務(wù)棧中啟動(dòng):

Intent intent = new Intent(this, YourActivity.class);   
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);   
startActivity(intent);

至于為什么要添加newtask大家可以點(diǎn)這里查看份名。

7.前臺(tái)服務(wù)

服務(wù)雖然會(huì)在后臺(tái)運(yùn)行,但系統(tǒng)在內(nèi)存不足的時(shí)候妓美,也會(huì)考慮將其終止僵腺,所以為了提高Service的存活率,我們可以通過(guò)啟動(dòng)前臺(tái)服務(wù)的方式來(lái)提高它的優(yōu)先級(jí)壶栋,前臺(tái)服務(wù)其實(shí)就是在通知欄常駐一個(gè)通知辰如,一般音樂播放器都是這種方式來(lái)處理的。

注意:前臺(tái)服務(wù)startForeground是android8.0特有的贵试,也就是說(shuō)8.0前后需要進(jìn)行適配琉兜,8.0之前繼續(xù)使用原來(lái)的NotificationCompat.Builder來(lái)創(chuàng)建通知,并設(shè)置setOngoing(true)來(lái)保持通知常駐毙玻,8.0以及8.0之后直接startForeground啟動(dòng)即可豌蟋。

這里不介紹通知的使用,具體大家可以自行查看桑滩,8.0通知改動(dòng)挺大梧疲,新增了channel的概念,大家可以自行g(shù)oogle了解运准。

下面來(lái)看下它的具體用法:

public class ForegroundService extends Service {
    private NotificationManager notificationManager;

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public void onCreate() {

        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Intent intentForeSerive = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intentForeSerive, 0);
        //8.0以及8.0之后
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (null == notificationManager.getNotificationChannel("fore_service")) {
                NotificationChannel channel = new NotificationChannel("fore_service", "前臺(tái)服務(wù)", NotificationManager.IMPORTANCE_HIGH);
                notificationManager.createNotificationChannel(channel);
            }
            Notification notification = new NotificationCompat.Builder(this, "fore_service")
                    .setContentTitle("This is content title")
                    .setContentText("This is content text")
                    .setWhen(System.currentTimeMillis())
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentIntent(pendingIntent)
                    .build();
            startForeground(1, notification);
        }else {
            //8.0之前的版本
            Notification notification = new NotificationCompat.Builder(this, "fore_service")
                    .setContentTitle("This is content title")
                    .setContentText("This is content text")
                    .setWhen(System.currentTimeMillis())
                    .setAutoCancel(false)
                    .setOngoing(true)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentIntent(pendingIntent)
                    .build();
            notificationManager.notify(1,notification);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public int onStartCommand(Intent intent, int flags, final int startId) {

        int flag = intent.getIntExtra("flag",0);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if(flag == 0){
                //關(guān)閉前臺(tái)服務(wù)
                stopForeground(true);
                stopSelf();
            }
        }else {
            if(flag == 0){
                //關(guān)閉通知
                notificationManager.cancel(1);
                stopSelf();
            }
        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

我通過(guò)一個(gè)按鈕來(lái)啟動(dòng)服務(wù)和關(guān)閉服務(wù):

private int currentFlag = 1;

//點(diǎn)擊按鈕之后執(zhí)行如下代碼
Intent intent = new Intent(MainActivity.this, ForegroundService.class);
intent.putExtra("flag",currentFlag);
startService(intent);
if(currentFlag == 1){
     currentFlag = 0;
}else {
     currentFlag = 1;
}

運(yùn)行效果如下:


打開和關(guān)閉前臺(tái)服務(wù)

8.Android 5.0之后必須顯式啟動(dòng)Service

在上面的例子中幌氮,我們都是使用Intent指定Service.class的方式顯式啟動(dòng)的,那么我們?cè)?.0以上的模擬器上運(yùn)行如下代碼:

    <service android:name=".MyService">
            <intent-filter>
                <action android:name="com.wangkeke.service.test"/>
                <category android:name="android.intent.category.default" />
            </intent-filter>
        </service>

    Intent intent = new Intent();
    intent.setAction("com.wangkeke.service.test");
    startService(intent);

話不多說(shuō)胁澳,直接運(yùn)行并點(diǎn)擊啟動(dòng)Service该互,正如我們"期待的那樣",崩潰出現(xiàn)了>禄慢洋!


5.0之后不能隱式啟動(dòng)Service

注意注意:Android 5.0之后必須顯式啟動(dòng)ServiceL瘤ā!普筹!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末败明,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子太防,更是在濱河造成了極大的恐慌妻顶,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜒车,死亡現(xiàn)場(chǎng)離奇詭異讳嘱,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)酿愧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門沥潭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人嬉挡,你說(shuō)我怎么就攤上這事钝鸽。” “怎么了庞钢?”我有些...
    開封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵拔恰,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我基括,道長(zhǎng)颜懊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任风皿,我火速辦了婚禮河爹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘桐款。我一直安慰自己咸这,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開白布鲁僚。 她就那樣靜靜地躺著炊苫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪冰沙。 梳的紋絲不亂的頭發(fā)上侨艾,一...
    開封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音拓挥,去河邊找鬼唠梨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛侥啤,可吹牛的內(nèi)容都是我干的当叭。 我是一名探鬼主播茬故,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蚁鳖!你這毒婦竟也來(lái)了磺芭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤醉箕,失蹤者是張志新(化名)和其女友劉穎钾腺,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體讥裤,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡放棒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了己英。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片间螟。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖损肛,靈堂內(nèi)的尸體忽然破棺而出厢破,到底是詐尸還是另有隱情,我是刑警寧澤荧关,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布溉奕,位于F島的核電站褂傀,受9級(jí)特大地震影響忍啤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜仙辟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一同波、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧叠国,春花似錦未檩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至项棠,卻和暖如春悲雳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背香追。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工合瓢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人透典。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓晴楔,卻偏偏與公主長(zhǎng)得像顿苇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子税弃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

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