Android Hilt:強大的依賴注入框架南誊,高級傳參解個耦

一身诺、Hilt 干依賴注入的

Hilt是干嘛的

Hilt蜜托,一個依賴注入框架,谷歌搞出來的霉赡,基于Dagger橄务,但是更加簡潔易用。

什么是依賴注入 (Dependency Injection)

依賴注入是一種設計模式穴亏。主要就是解耦蜂挪!解耦!解耦嗓化!棠涮。

依賴注入是一種設計模式,它通過在對象之間傳遞依賴關系刺覆,使得對象能夠更靈活严肪、可測試和可維護。在Android開發(fā)中谦屑,依賴注入可以幫助我們管理和解耦應用程序中的各種組件,如Activity、Fragment很洋、ViewModel喉磁、Repository等。

既生Dagger 何生 Hilt 涝焙?

安卓中的Hilt是一種用于依賴注入(Dependency Injection)的庫仑撞。Hilt是由Google開發(fā)的妖滔,它是基于Dagger的一個擴展庫座舍,旨在簡化Android應用程序中的依賴注入過程。

Hilt提供了一套注解和生成代碼采蚀,用于在Android應用程序中自動完成依賴注入的配置。它簡化了Dagger的使用纲爸,減少了樣板代碼的編寫缩焦,提高了開發(fā)效率责静。

Hilt還提供了一些特定于Android的功能灾螃,如對Android組件的注入支持,以及在不同生命周期中管理依賴關系的能力嵌赠。

Hilt 大概怎么用

  • Application 注解下
  • 在需要的標記為依賴注入的Activity姜挺、Fragment注解下 @AndroidEntryPoint

使用Hilt進行依賴注入時炊豪,首先需要在應用程序的Application類上添加@HiltAndroidApp注解拧篮,以告知Hilt該應用程序將使用Hilt進行依賴注入串绩。然后,可以在其他組件(如Activity高氮、Fragment)中使用@AndroidEntryPoint注解來標記需要進行依賴注入的地方纫溃。Hilt會根據注解生成必要的代碼韧掩,在運行時完成依賴注入。

Hilt還提供了一些其他的注解费彼,用于標記和配置依賴關系口芍。例如鬓椭,

  • 可以使用@Inject注解來標記需要注入的依賴項,
  • 使用@Module注解來標記用于提供依賴項的模塊類翘瓮,
  • 使用@Provides注解來標記提供依賴項的方法等资盅。

二踊赠、什么是TM的依賴注入筐带,給個例子

比如我們創(chuàng)建一輛汽車,汽車需要引擎荣赶。

  • 如果不用依賴注入,創(chuàng)建汽車利诺,汽車內部還要創(chuàng)建引擎慢逾,這樣就 耦合 耦合 偶爾
  • 如果使用依賴注入,創(chuàng)建汽車不需要創(chuàng)建引擎口注,而是從外部將Engine對象傳遞Car類寝志,這樣就 解耦 解耦 解耦

不使用依賴注入,汽車內部創(chuàng)建引擎毫缆,耦合耦合耦合乐导,

class Engine {
    void start() {
        System.out.println("Engine started");
    }
}

class Car {
    private Engine engine;

    Car() {
        engine = new Engine();  // Car類自己創(chuàng)建Engine對象
    }

    void drive() {
        engine.start();
        System.out.println("Car is driving");
    }
}

使用依賴注入物臂,傳遞引擎對象給汽車,汽車內部不創(chuàng)建引擎對象蛾狗,解耦解耦解耦

class Car {
    private Engine engine;

    Car(Engine engine) {  // Engine對象通過構造函數(shù)注入
        this.engine = engine;
    }

    void drive() {
        engine.start();
        System.out.println("Car is driving");
    }
}

現(xiàn)在淘太,我們可以在創(chuàng)建Car對象時蒲牧,把一個Engine對象傳遞給它:

Engine engine = new Engine();
Car car = new Car(engine);
car.drive();


上面的對比赌莺。雖然簡單艘狭,但是是個挺好的例子

"Engine對象通過構造函數(shù)注入"是指我們通過Car類的構造函數(shù)將Engine對象傳遞給Car類。這是一種依賴注入的方式遵倦,被稱為構造函數(shù)注入梧躺。

在這個例子中傲绣,Car類需要一個Engine對象來工作秃诵。在沒有使用依賴注入的情況下,Car類會自己創(chuàng)建一個Engine對象禁舷。但這樣做的問題是,Car類與Engine類緊密耦合在一起在讶,如果我們想要更換一個不同類型的Engine构哺,或者我們想要在測試時使用一個模擬的Engine战坤,我們就需要修改Car類的代碼途茫。

當我們使用構造函數(shù)注入時,我們不再在Car類內部創(chuàng)建Engine對象娜扇,而是在創(chuàng)建Car對象時雀瓢,從外部將Engine對象傳遞給Car類刃麸。這樣司浪,Car類就不再依賴于Engine類的具體實現(xiàn)啊易,我們可以很容易地更換不同類型的Engine,或者在測試時使用一個模擬的Engine箱蝠,而不需要修改Car類的代碼。

也許你會說牙瓢,不就是傳個參嗎矾克,說得這么麻煩?酒繁?州袒?? 某種程度上他匪,你可以這么說邦蜜,當時亥至,這個玩意姐扮,能放大了玩。


依賴注入杯缺,可不僅僅是高級的傳參 (李姐會理解)

人家萍肆,可傳參胀屿,牛逼多了宿崭。

    1. Activity和Fragment:在Android開發(fā)中,Activity和Fragment經常需要訪問一些共享的資源或服務奖蔓,例如網絡請求Retrofit吆鹤、數(shù)據庫訪問疑务、ViewModel等。如果沒有依賴注入知允,我們可能需要在每個Activity或Fragment中手動創(chuàng)建這些對象温鸽,這會導致代碼重復,而且使得Activity和Fragment與這些服務緊密耦合配椭,難以進行單元測試股缸。通過使用依賴注入敦姻,我們可以在一個統(tǒng)一的地方配置這些服務歧杏,然后在需要的地方自動注入,這使得代碼更加清晰旺入,更容易測試凯力。
    1. 主App和Module:在一個模塊化的應用中,不同的模塊可能需要訪問一些共享的服務拗秘。如果沒有依賴注入祈惶,我們可能需要通過一些復雜的方式來讓這些模塊獲取到這些服務捧请,這會使得代碼變得復雜疹蛉,而且難以管理。通過使用依賴注入讹蘑,我們可以在主App中配置這些服務座慰,然后在各個模塊中自動注入版仔,這使得代碼更加清晰误墓,更容易管理谜慌。
  • 3、管理單例依賴項:在 Android 應用程序中变泄,有一些依賴項是單例的妨蛹,如數(shù)據庫蛙卤、網絡客戶端等噩死。使用 Hilt 可以更輕松地管理這些單例依賴項甜滨,同時避免了手動管理單例依賴項的復雜性衣摩。

這個說是不是不會覺得是簡答傳參了!

依賴注入使得我們的代碼更加模塊化既琴,每個類都只關注自己的職責甫恩,不需要關心其依賴對象的創(chuàng)建和管理磺箕。這使得我們的代碼更容易重用。


三简僧、Hilt的一些常見注解

在開始app例子之前雕欺,還需要需要將一些注解前面說明一下岛马。

Hilt使用了一系列的注解來簡化依賴注入的過程啦逆。以下是一些最常用的Hilt注解:

@HiltAndroidApp

  1. @HiltAndroidApp: 這個注解用于Application類夏志,它會觸發(fā)Hilt的代碼生成撞蜂,包括一個應用級別的組件蝌诡,這個組件可以為其他Hilt組件(如Activity組件)提供依賴。
@HiltAndroidApp
class MyApplication : Application()


@AndroidEntryPoint

  1. @AndroidEntryPoint: 這個注解用于Android組件宇色,如Activity宣蠕、Fragment抢蚀、Service等皿曲,它告訴Hilt這些組件可以接收依賴注入吴侦。
@AndroidEntryPoint class MainActivity : AppCompatActivity() { @Inject lateinit var someClass: SomeClass }

@Inject

  1. @Inject: 這個注解用于字段备韧、構造函數(shù)或方法,告訴Hilt需要注入依賴叠艳。對于字段附较,Hilt會自動注入相應的依賴翅睛;對于構造函數(shù)捕发,Hilt會使用它來創(chuàng)建類的實例扎酷;對于方法遏匆,Hilt會在注入后調用它幅聘。
class SomeClass @Inject constructor(private val someDependency: SomeDependency)


@Module

  1. @Module: 這個注解用于對象帝蒿,這些對象提供了一系列的依賴提供方法葛超。這些方法用@Provides注解標記绣张,Hilt會在需要時調用它們。

@Provides

  1. @Provides: 這個注解用于在@Module注解的類中的方法沼撕,這些方法提供了依賴的實例端朵。Hilt會在需要時調用這些方法燃箭。
@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    @Singleton
    @Provides
    fun provideSomeDependency(): SomeDependency {
        return SomeDependency()
    }
}


@InstallIn

  1. @InstallIn: 這個注解用于@Module注解的類敬拓,指定這個模塊安裝在哪個Hilt組件中。

@Singleton

  1. @Singleton: 這個注解用于@Provides注解的方法或@Inject注解的構造函數(shù)厕诡,告訴Hilt提供的依賴是單例的营勤。
@Singleton
class SomeSingletonClass @Inject constructor()

@ViewModelInject

  1. @ViewModelInject: 這個注解用于ViewModel的構造函數(shù)葛作,告訴Hilt如何創(chuàng)建ViewModel的實例。
class MyViewModel @ViewModelInject constructor(private val repository: Repository) : ViewModel()


@Assisted

  1. @Assisted:用于標記 ViewModel 的構造函數(shù)參數(shù)绪穆,以便在使用 assisted injection 時注入這些參數(shù)玖院。

@AssistedInject

  1. @AssistedInject:用于標記使用 assisted injection 創(chuàng)建的 ViewModel 的構造函數(shù)难菌。

這些注解使得Hilt能夠自動處理依賴的創(chuàng)建和注入扔傅,大大簡化了依賴注入的過程猎塞。

注解 描述
@HiltAndroidApp 用于Application類荠耽,觸發(fā)Hilt的代碼生成铝量,包括一個應用級別的組件慢叨,這個組件可以為其他Hilt組件(如Activity組件)提供依賴拍谐。
@AndroidEntryPoint 用于Android組件轩拨,如Activity亡蓉、Fragment、Service等淋肾,告訴Hilt這些組件可以接收依賴注入巫员。
@Inject 用于字段構造函數(shù)方法感猛,告訴Hilt需要注入依賴奢赂。對于字段咱士,Hilt會自動注入相應的依賴序厉;對于構造函數(shù)弛房,Hilt會使用它來創(chuàng)建類的實例文捶;對于方法粹排,Hilt會在注入后調用它顽耳。
@Module 用于對象斧抱,這些對象提供了一系列的依賴提供方法弄抬。這些方法用@Provides注解標記掂恕,Hilt會在需要時調用它們弛槐。
@Provides 用于在@Module注解的類中的方法苟弛,這些方法提供了依賴的實例。Hilt會在需要時調用這些方法忿项。
@InstallIn 用于@Module注解的類钧唐,指定這個模塊安裝在哪個Hilt組件中。
@Singleton 用于@Provides注解的方法或@Inject注解的構造函數(shù)匠襟,告訴Hilt提供的依賴是單例的钝侠。
@ViewModelInject 用于ViewModel的構造函數(shù),告訴Hilt如何創(chuàng)建ViewModel的實例酸舍。
  • @Module@Provides:這兩個注解通常一起使用帅韧,定義在一個類中,這個類提供了一系列的依賴提供方法啃勉。這些方法用@Provides注解標記弱匪,Hilt會在需要時調用它們。

四璧亮、上個App

四、1帘饶、hilt準備

app目錄下 build.gradle


plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    // 添加kapt注解處理器
    id 'kotlin-kapt'
    // hilt所需
    id 'com.google.dagger.hilt.android'
}




dependencies {
    implementation 'com.google.dagger:hilt-android:2.44'
    kapt 'com.google.dagger:hilt-android-compiler:2.44'
}


項目級別build

plugins {
    id 'com.android.application' version '8.0.0' apply false
    id 'com.android.library' version '8.0.0' apply false
    id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
    // hilt
    id "com.google.dagger.hilt.android"  version "2.44" apply false
}


這里需要說明一下,比較新的版本是如上這么寫暑劝。

如果是比較舊的android studio丢氢,則是classpath的寫法蒸走。比如:

buildscript {
    dependencies {

        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.44'
    }
}


以上别惦,配置完成益楼。

四.2、汽車和引擎的例子

// 使用 @HiltAndroidApp 注解標記一個應用,這是使用 Hilt 進行依賴注入的入口點族跛。
// Hilt 需要一個入口點來提供依賴桐绒,這通常是 AndroidApplication 類咧叭。
// 這個注解會觸發(fā) Hilt 的代碼生成颖变,生成的代碼包括一個應用級別的組件,這個組件可以為其他 Hilt 組件(如 Activity 組件)提供依賴佩脊。
@HiltAndroidApp
class MyApplication : Application() {
    // 這個類通常不需要寫任何代碼,除非你需要在應用啟動時執(zhí)行一些操作。
}


android:name=".MyApplication"


Engine


// 使用 @Inject 注解標記構造函數(shù)慨代,告訴 Hilt 如何創(chuàng)建這個類的實例。
// 當 Hilt 需要提供一個 Engine 實例時妇汗,它會調用這個構造函數(shù)告唆。
// 在這個例子中,Engine 類沒有任何依賴,所以構造函數(shù)沒有任何參數(shù)畜侦。
class Engine @Inject constructor() {
    fun start() {
        println("Engine started")
    }
}


Car

// 使用 @Inject 注解標記構造函數(shù)验懊,告訴 Hilt 如何創(chuàng)建這個類的實例召烂。
// 當 Hilt 需要提供一個 Car 實例時,它會調用這個構造函數(shù)漫谷。
// 在這個例子中,Car 類依賴于 Engine 類俺祠,所以構造函數(shù)有一個 Engine 類型的參數(shù)肺然。
// Hilt 會查找提供 Engine 實例的方法(在這個例子中吐葱,就是 Engine 類的構造函數(shù)),然后用提供的 Engine 實例來創(chuàng)建 Car 實例。
class Car @Inject constructor(private val engine: Engine) {
    fun drive() {
        engine.start()
        println("Car is driving")
    }
}

Activity

/**
 *
 *  使用 @AndroidEntryPoint 注解標記一個 Android 組件喝噪,告訴 Hilt 這個組件可以接收依賴注入巫财。
 *  Hilt 支持多種 Android 組件闽瓢,包括 Activity荔燎、Fragment摔吏、View、Service、BroadcastReceiver 等塑顺。
 *  當一個組件被標記為 @AndroidEntryPoint挤牛,Hilt 會為這個組件生成一個組件類(在這個例子中,是 MainActivityComponent)竣蹦。
 *  這個組件類是用來提供依賴的纲菌,它是由 Hilt 自動生成的,你無需手動創(chuàng)建喜德。
 */

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    @Inject
    lateinit var car: Car

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // Use the car
        car.drive()
    }
}

運行結果:

System.out: Engine started
System.out: Car is driving

嗯。如果只是這么用,那么確實平平無奇沫屡,仿佛是一個高級傳參驶俊。 但是想鹰,如果只是這樣,那我們還H個什么H蝙云。

但是廷区,這是一個挺好的小例子。


五锋勺、實際開發(fā)中一些常用的場景

SharedPreferences的注入

// 創(chuàng)建一個Hilt模塊,用于提供SharedPreferences實例
@Module
@InstallIn(SingletonComponent::class)
object SharedPreferencesModule {

    @Provides
    fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences {
        return context.getSharedPreferences("pref_name", Context.MODE_PRIVATE)
    }
}

// 在Activity中棵譬,你可以使用@Inject注解來請求一個SharedPreferences實例。
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var sharedPreferences: SharedPreferences

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

        // 使用SharedPreferences
        val editor = sharedPreferences.edit()
        editor.putString("key", "value")
        editor.apply()
    }
}


上述代碼中趾唱,@AndroidEntryPoint是一個Hilt注解蜻懦,用于指示Hilt應該為這個Activity提供依賴征炼。然后,通過在sharedPreferences字段上添加@Inject注解肋坚,Hilt就會知道它需要為這個字段提供一個SharedPreferences實例葵第。這個實例是由SharedPreferencesModule模塊中的provideSharedPreferences方法提供的屏镊。

注意膀值,你可以隨時使用sharedPreferences字段棍丐,Hilt會確保在onCreate方法調用時秘案,它已經被正確初始化。

你也可以將這種模式應用于其他的例子,例如網絡服務裕膀、視圖模型访忿、數(shù)據庫和數(shù)據倉庫等。

多模塊項目

在多模塊項目中,Hilt可以幫助你更好地管理跨模塊的依賴刺啦。例如留特,假設你有一個data模塊和一個app模塊,data模塊提供了一個Repository類玛瘸,app模塊需要使用這個Repository蜕青。

首先,在data模塊中糊渊,你定義了一個Repository類市咆,并用@Inject注解標記其構造函數(shù):

// 在 data 模塊中
class Repository @Inject constructor() {
    // ...
}

然后,在app模塊中再来,你可以直接在需要的地方注入Repository

// 在 app 模塊中
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject lateinit var repository: Repository

    // ...
}


在這個例子中蒙兰,你不需要在app模塊中手動創(chuàng)建Repository的實例磷瘤,Hilt會自動為你處理。


再來一個依賴管理的例子

以為簡化的Retrofit為例子

假設我們有一個NetworkModule搜变,它提供了一個Retrofit實例:

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

    @Singleton
    @Provides
    fun provideRetrofit(): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .build()
    }
}


在這個例子中采缚,NetworkModule是一個Hilt模塊,它在應用級別的組件(SingletonComponent)中提供了一個Retrofit實例挠他。這個Retrofit實例是一個單例扳抽,因為我們使用了@Singleton注解。

然后殖侵,我們有一個Repository類贸呢,它需要這個Retrofit實例來發(fā)起網絡請求:

class Repository @Inject constructor(private val retrofit: Retrofit) {
    // ...
}


在這個例子中,Repository類通過構造函數(shù)注入獲取了Retrofit實例拢军。我們不需要手動創(chuàng)建Retrofit實例楞陷,Hilt會自動為我們處理。

最后茉唉,我們有一個ViewModel固蛾,它需要這個Repository來獲取數(shù)據:

class MyViewModel @ViewModelInject constructor(private val repository: Repository) : ViewModel() {
    // ...
}


在這個例子中,MyViewModel通過@ViewModelInject注解獲取了Repository實例度陆。我們不需要手動創(chuàng)建Repository實例艾凯,Hilt會自動為我們處理。

這就是一個典型的依賴鏈:MyViewModel依賴于Repository懂傀,Repository依賴于Retrofit趾诗。通過Hilt,我們可以輕松地管理這個依賴鏈蹬蚁,而無需手動創(chuàng)建和管理每個依賴恃泪。這使得代碼更加清晰和直觀,也使得新成員更容易理解項目的結構缚忧。


ViewModel注入

// Hilt提供了一個HiltViewModel注解悟泵,它允許你在ViewModel的構造函數(shù)中使用@Inject。
@HiltViewModel
class MyViewModel @Inject constructor(private val userRepository: UserRepository) : ViewModel() {
    // ...
}

// 在Activity或Fragment中闪水,你可以使用由Hilt提供的ViewModel實例糕非。
@AndroidEntryPoint
class MyActivity : AppCompatActivity() {

    private val viewModel: MyViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // Use viewModel here
    }
}


數(shù)據庫的注入

// 創(chuàng)建一個Hilt模塊,用于提供Room數(shù)據庫實例
@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {

    @Provides
    fun provideDatabase(@ApplicationContext context: Context): MyDatabase {
        return Room.databaseBuilder(
            context,
            MyDatabase::class.java, "database-name"
        ).build()
    }

    @Provides
    fun provideUserDao(database: MyDatabase): UserDao {
        return database.userDao()
    }
}

// 在需要UserDao的地方球榆,使用@Inject注解來請求一個UserDao實例朽肥。
class UserRepository @Inject constructor(private val userDao: UserDao) {
    // ...
}



不是每一個Activity都需要依賴注入,如果這個activity只在當前頁面使用持钉,那么沒必要依賴注入衡招。


Hilt篇,大概就到這里吧每强。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末始腾,一起剝皮案震驚了整個濱河市州刽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌浪箭,老刑警劉巖穗椅,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異奶栖,居然都是意外死亡匹表,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門宣鄙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來袍镀,“玉大人,你說我怎么就攤上這事冻晤∥郏” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵明也,是天一觀的道長宣虾。 經常有香客問我惯裕,道長温数,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任蜻势,我火速辦了婚禮撑刺,結果婚禮上,老公的妹妹穿的比我還像新娘握玛。我一直安慰自己够傍,他們只是感情好,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布挠铲。 她就那樣靜靜地躺著冕屯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拂苹。 梳的紋絲不亂的頭發(fā)上安聘,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音瓢棒,去河邊找鬼浴韭。 笑死,一個胖子當著我的面吹牛脯宿,可吹牛的內容都是我干的念颈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼连霉,長吁一口氣:“原來是場噩夢啊……” “哼榴芳!你這毒婦竟也來了嗡靡?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤窟感,失蹤者是張志新(化名)和其女友劉穎叽躯,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肌括,經...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡点骑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了谍夭。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片黑滴。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖紧索,靈堂內的尸體忽然破棺而出袁辈,到底是詐尸還是另有隱情,我是刑警寧澤珠漂,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布晚缩,位于F島的核電站,受9級特大地震影響媳危,放射性物質發(fā)生泄漏荞彼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一待笑、第九天 我趴在偏房一處隱蔽的房頂上張望鸣皂。 院中可真熱鬧,春花似錦暮蹂、人聲如沸寞缝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荆陆。三九已至,卻和暖如春集侯,著一層夾襖步出監(jiān)牢的瞬間被啼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工浅悉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留趟据,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓术健,卻偏偏與公主長得像汹碱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子荞估,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內容