Context是什么

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? Context

?? Context熙含,翻譯是上下文環(huán)境各吨,在android應(yīng)用開發(fā)中的地位舉足輕重胁住,甚至源碼也有一句話:everything needs a context(看到過筹吐,但是忘了在哪里了)猛频。


Context類圖結(jié)構(gòu)

從這個類圖中我們看到狮崩,Context是一個抽象類,一邊是Context的具體實現(xiàn)ContextImpl鹿寻,一邊則是組件的封裝類ContextWrapper睦柴,便于二者各司其職,我理解是接口和實現(xiàn)分開毡熏,這樣比較符合開閉原則吧坦敌。

? 既然要搞清楚Context是干嘛的,得先看Context的實例什么時候創(chuàng)建的招刹。這里有兩個我們經(jīng)常接觸的組件恬试,Activity和Service,以及用的較少的Application疯暑,它們的關(guān)系如下:

? ? 1.Application:保存應(yīng)用的全局信息的類训柴,它的實例在應(yīng)用創(chuàng)建的時候被創(chuàng)建,生命周期最長妇拯,應(yīng)用銷毀了才會被銷毀幻馁。

? ? 2.Activity:創(chuàng)建一個Activity便對應(yīng)一個Context的實例,生命周期隨著Activity的周期變化越锈。

? ? 3.Service:創(chuàng)建一個Service便對應(yīng)一個Context的實例仗嗦,生命周期隨著Service的周期變化。

下面逐一看看它們是什么時候?qū)嵗鼵ontext類的甘凭,我們需要知道稀拐,一個ContextWrapper類對應(yīng)一個ContextImpl類的實例,因為具體實現(xiàn)的地方還是在ContextImpl中丹弱,ContextWrapper中的mBase變量指向ContextImpl變量的實例德撬。


(1) Application的Context創(chuàng)建:

如圖:


Application的創(chuàng)建過程

? 跳過Process創(chuàng)建過程,在我們的應(yīng)用被zygote進(jìn)程孵化出來后躲胳,被反射調(diào)用main函數(shù)蜓洪,這里會創(chuàng)建ActivityThread類的實例,該類并不是一個線程類的子類坯苹,但是它的main函數(shù)跑在新創(chuàng)建的進(jìn)程的主線程隆檀。 創(chuàng)建后,調(diào)用attach方法,與AMS綁定:

```java

private void attach(boolean system) {

? ? if (!system) {

? ? ? ? final IActivityManager mgr = ActivityManager.getService();

? ? ? ? try {

? ? ? ? ? ? mgr.attachApplication(mAppThread);? // final ApplicationThread mAppThread = new ApplicationThread();

? ? ? ? } catch (RemoteException ex) {

? ? ? ? ? ? throw ex.rethrowFromSystemServer();

? ? ? ? }

? ? }

}

```

這里傳入的mAppThread變量為ApplicationThread類恐仑,它為ActivityThread的內(nèi)部類泉坐,作用就是作為應(yīng)用端的binder服務(wù)端,負(fù)責(zé)接收AMS的調(diào)度菊霜,這里我們傳入這個服務(wù)端的句柄坚冀,讓AMS持有济赎,從而AMS可以通過這個句柄來操控應(yīng)用的行為鉴逞。我們向AMS請求,則是通過AMS的句柄司训。接下來就到了AMS的邏輯:

@Override

public final void attachApplication(IApplicationThread thread) {

?? synchronized (this) {

? ? ?? int callingPid = Binder.getCallingPid();

? ? ?? final long origId = Binder.clearCallingIdentity();

? ? ?? attachApplicationLocked(thread, callingPid);

? ? ?? Binder.restoreCallingIdentity(origId);

?? }

}

-----------------------------------------------------------------------

?? private final boolean attachApplicationLocked(IApplicationThread thread,

? ? ? ? ?? int pid) {

? ? ? ? ?? ProcessRecord app;? //app進(jìn)程的各種信息

? ? ? ? ?? app.makeActive(thread, mProcessStats);? //將IApplicationThread對象保存到ProcessRecord中

? ? ? ? ?? if (app.instr != null) {

? ? ? ? ? ? ?? thread.bindApplication(processName, appInfo, providers,? //通知客戶端創(chuàng)建Application對象

? ? ? ? ? ? ? ? ? ? ?? app.instr.mClass,

? ? ? ? ? ? ? ? ? ? ?? profilerInfo, app.instr.mArguments,

? ? ? ? ? ? ? ? ? ? ?? app.instr.mWatcher,

? ? ? ? ? ? ? ? ? ? ?? app.instr.mUiAutomationConnection, testMode,

? ? ? ? ? ? ? ? ? ? ?? mBinderTransactionTrackingEnabled, enableTrackAllocation,

? ? ? ? ? ? ? ? ? ? ?? isRestrictedBackupMode || !normalMode, app.persistent,

? ? ? ? ? ? ? ? ? ? ?? new Configuration(getGlobalConfiguration()), app.compat,

? ? ? ? ? ? ? ? ? ? ?? getCommonServicesLocked(app.isolated),

? ? ? ? ? ? ? ? ? ? ?? mCoreSettingsObserver.getCoreSettingsLocked(),

? ? ? ? ? ? ? ? ? ? ?? buildSerial);

? ? ? ? ?? } else {

? ? ? ? ? ? ?? thread.bindApplication(processName, appInfo, providers, null, profilerInfo,

? ? ? ? ? ? ? ? ? ? ?? null, null, null, testMode,

? ? ? ? ? ? ? ? ? ? ?? mBinderTransactionTrackingEnabled, enableTrackAllocation,

? ? ? ? ? ? ? ? ? ? ?? isRestrictedBackupMode || !normalMode, app.persistent,

? ? ? ? ? ? ? ? ? ? ?? new Configuration(getGlobalConfiguration()), app.compat,

? ? ? ? ? ? ? ? ? ? ?? getCommonServicesLocked(app.isolated),

? ? ? ? ? ? ? ? ? ? ?? mCoreSettingsObserver.getCoreSettingsLocked(),

? ? ? ? ? ? ? ? ? ? ?? buildSerial);

? ? ? ? ?? }

? ? ?? return true;

?? }

? ? 在ApplicationThread的實現(xiàn)端中构捡,就是把跨進(jìn)程傳遞過來的各種數(shù)據(jù)再用一個AppBindData類保存下來,然后調(diào)用Handler對象H發(fā)送消息BIND_APPLICATION壳猜,最后在app線程中處理此邏輯勾徽,讓AMS線程可以不必同步阻塞。接下來就到了handleBindApplication:

private void handleBindApplication(AppBindData data) {

?? mBoundApplication = data;

?? final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);

?? updateLocaleListFromAppContext(appContext,

? ? ? ? ?? mResourcesManager.getConfiguration().getLocales());

?? if (ii != null) {

? ? ?? final ApplicationInfo instrApp = new ApplicationInfo();

? ? ?? ii.copyTo(instrApp);

? ? ?? instrApp.initForUser(UserHandle.myUserId());

? ? ?? final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,

? ? ? ? ? ? ?? appContext.getClassLoader(), false, true, false);

? ? ?? final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

? ? ?? try {

? ? ? ? ?? final ClassLoader cl = instrContext.getClassLoader();

? ? ? ? ?? mInstrumentation = (Instrumentation) ? //創(chuàng)建Instrumentation類對象

? ? ? ? ? ? ?? cl.loadClass(data.instrumentationName.getClassName()).newInstance();

? ? ?? } catch (Exception e) {

? ? ? ? ?? throw new RuntimeException(

? ? ? ? ? ? ?? "Unable to instantiate instrumentation "

? ? ? ? ? ? ?? + data.instrumentationName + ": " + e.toString(), e);

? ? ?? }

? ? ?? final ComponentName component = new ComponentName(ii.packageName, ii.name);

? ? ?? mInstrumentation.init(this, instrContext, appContext, component,

? ? ? ? ? ? ?? data.instrumentationWatcher, data.instrumentationUiAutomationConnection);? //初始化Instrumentation

?? try {

? ? ?? // If the app is being launched for full backup or restore, bring it up in

? ? ?? // a restricted environment with the base application class.

? ? ?? Application app = data.info.makeApplication(data.restrictedBackupMode, null);? //創(chuàng)建Application類對象

? ? ?? mInitialApplication = app;

? ? ?? }

}

? ? Instrumentation類是用于管理Acitivty的工具類统扳。這又有一個比較重要的對象出現(xiàn)喘帚,LoadedApk,它里面保存了類加載器ClassLoader咒钟,data.info的對象便是它吹由,makeApplication函數(shù)中的邏輯:

public Application makeApplication(boolean forceDefaultAppClass,

? ? ?? Instrumentation instrumentation) {

?? if (mApplication != null) {? //保證唯一性,不會重復(fù)創(chuàng)建Application對象朱嘴,所以我們可以認(rèn)為Application對象是單例的

? ? ?? return mApplication;

?? }

?? Application app = null;

?? String appClass = mApplicationInfo.className;

?? try {

? ? ?? java.lang.ClassLoader cl = getClassLoader();? //獲取類加載器實例

? ? ?? ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); //創(chuàng)建ContextImpl實例

? ? ?? app = mActivityThread.mInstrumentation.newApplication( ? //實際創(chuàng)建Application對象的地方

? ? ? ? ? ? ?? cl, appClass, appContext); ?

? ? ?? appContext.setOuterContext(app);

?? } catch (Exception e) {

? ? ?? if (!mActivityThread.mInstrumentation.onException(app, e)) {

? ? ? ? ?? Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

? ? ? ? ?? throw new RuntimeException(

? ? ? ? ? ? ?? "Unable to instantiate application " + appClass

? ? ? ? ? ? ?? + ": " + e.toString(), e);

? ? ?? }

?? }

?? mActivityThread.mAllApplications.add(app);

?? mApplication = app;

?? if (instrumentation != null) {

? ? ?? try {

? ? ? ? ?? instrumentation.callApplicationOnCreate(app); ? //Application的onCreate()被調(diào)用

? ? ?? } catch (Exception e) {

? ? ? ? ?? if (!instrumentation.onException(app, e)) {

? ? ? ? ? ? ?? Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

? ? ? ? ? ? ?? throw new RuntimeException(

? ? ? ? ? ? ? ? ?? "Unable to create application " + app.getClass().getName()

? ? ? ? ? ? ? ? ?? + ": " + e.toString(), e);

? ? ? ? ?? }

? ? ?? }

?? }

?? return app;

}

? 這里我們看到了ContextImpl的創(chuàng)建時機(jī)倾鲫,就是在Application實例創(chuàng)建的時候:

?? public Application newApplication(ClassLoader cl, String className, Context context)

? ? ? ? ?? throws InstantiationException, IllegalAccessException,

? ? ? ? ?? ClassNotFoundException {

? ? ?? return newApplication(cl.loadClass(className), context);

?? }

----------------------------------------------------------------------------

static public Application newApplication(Class<?> clazz, Context context)

? ? ?? throws InstantiationException, IllegalAccessException,

? ? ?? ClassNotFoundException {

?? Application app = (Application)clazz.newInstance();

?? app.attach(context);

?? return app;

}

? 如此就完成了Application的創(chuàng)建,并且調(diào)用attach方法把Application的mBase對象賦值給創(chuàng)建的ContextImpl萍嬉,至此Application的創(chuàng)建就完成了乌昔,getApplicationContext() 返回的便是此處我們創(chuàng)建的Application類的對象。


? 這里為什么要去LoadedApk類中利用類加載器壤追,把對象創(chuàng)建出來呢磕道?因為我們的Application類是可以自己拓展的,創(chuàng)建的時候是不確定應(yīng)用自己是否復(fù)寫了Application對象行冰,利用類加載器就可以動態(tài)決定創(chuàng)建什么類的對象了溺蕉,我們只需要從PMS中獲取到application的具體類名即可,這個類名是寫在Mainfest文件中的资柔,后面Activity也是利用這種機(jī)制去創(chuàng)建對象焙贷。

(2)Actvity的啟動過程,網(wǎng)上非常多文章分析了贿堰,我也就不再重復(fù)羅列出來了赞咙,大概的過程就是startActivity()被調(diào)用,然后檢查目標(biāo)Acitivity的進(jìn)程是否創(chuàng)建杆煞,沒創(chuàng)建就先向Zygote進(jìn)程請求fork應(yīng)用進(jìn)程,然后一系列初始化過程后庶灿,最后在AMS模塊中的ActivityStackSupervisor中realStartActivityLocked()調(diào)用IApplicationThread代理類,調(diào)用到scheduleLaunchActivity()吃衅,然后在應(yīng)用的線程開始執(zhí)行handleLaunchActivity()往踢,最主要的邏輯在performLaunchActivity:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

?? ActivityInfo aInfo = r.activityInfo;

?? if (r.packageInfo == null) {

? ? ?? r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,

? ? ? ? ? ? ?? Context.CONTEXT_INCLUDE_CODE);

?? }

?? ContextImpl appContext = createBaseContextForActivity(r);? //創(chuàng)建ContextImpl對象實例

?? Activity activity = null;

?? try {

? ? ?? java.lang.ClassLoader cl = appContext.getClassLoader();

? ? ?? activity = mInstrumentation.newActivity( ? ? ? ? ? ?? //Activity對象創(chuàng)建

? ? ? ? ? ? ?? cl, component.getClassName(), r.intent);

? ? ?? StrictMode.incrementExpectedActivityCount(activity.getClass());

? ? ?? r.intent.setExtrasClassLoader(cl);

? ? ?? r.intent.prepareToEnterProcess();

? ? ?? if (r.state != null) {

? ? ? ? ?? r.state.setClassLoader(cl);

? ? ?? }

?? } catch (Exception e) {

? ? ?? if (!mInstrumentation.onException(activity, e)) {

? ? ? ? ?? throw new RuntimeException(

? ? ? ? ? ? ?? "Unable to instantiate activity " + component

? ? ? ? ? ? ?? + ": " + e.toString(), e);

? ? ?? }

?? }

?? try {

? ? ?? Application app = r.packageInfo.makeApplication(false, mInstrumentation); //應(yīng)用已經(jīng)創(chuàng)建過Application了,返回之前的對象

? ? ?? if (activity != null) {

? ? ? ? ?? appContext.setOuterContext(activity);

? ? ? ? ?? activity.attach(appContext, this, getInstrumentation(), r.token, ? //初始化activity

? ? ? ? ? ? ? ? ?? r.ident, app, r.intent, r.activityInfo, title, r.parent,

? ? ? ? ? ? ? ? ?? r.embeddedID, r.lastNonConfigurationInstances, config,

? ? ? ? ? ? ? ? ?? r.referrer, r.voiceInteractor, window, r.configCallback);

? ? ? ? ?? if (r.isPersistable()) {

? ? ? ? ? ? ?? mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);? //oncreate調(diào)用時機(jī)

? ? ? ? ?? } else {

? ? ? ? ? ? ?? mInstrumentation.callActivityOnCreate(activity, r.state);

? ? ? ? ?? }

? ? ? ? ?? if (!r.activity.mFinished) {

? ? ? ? ? ? ?? if (r.isPersistable()) {

? ? ? ? ? ? ? ? ?? if (r.state != null || r.persistentState != null) {

? ? ? ? ? ? ? ? ? ? ?? mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, //如果之前保存了數(shù)據(jù)徘层,可以在此恢復(fù)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? r.persistentState);

? ? ? ? ? ? ? ? ?? }

? ? ? ? ? ? ?? } else if (r.state != null) {

? ? ? ? ? ? ? ? ?? mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);

? ? ? ? ? ? ?? }

? ? ? ? ?? }

? ? ?? }

?? return activity;

}

? 至于Activity的生命周期后面怎么走的峻呕,這里不在乎,我們只看Context實例化過程趣效。同樣的瘦癌,這里也會創(chuàng)建ContextImpl對象,在Activity對象創(chuàng)建后跷敬,調(diào)用Attach()讯私,這個函數(shù)挺重要的,我們看看都干了什么:

final void attach(Context context, ActivityThread aThread,

? ? ?? Instrumentation instr, IBinder token, int ident,

? ? ?? Application application, Intent intent, ActivityInfo info,

? ? ?? CharSequence title, Activity parent, String id,

? ? ?? NonConfigurationInstances lastNonConfigurationInstances,

? ? ?? Configuration config, String referrer, IVoiceInteractor voiceInteractor,

? ? ?? Window window, ActivityConfigCallback activityConfigCallback) {

?? attachBaseContext(context); ? //同樣的西傀,會調(diào)用此函數(shù)為ContextWrapper中的mBase對象賦值一個創(chuàng)建的ContextImpl對象

?? mWindow = new PhoneWindow(this, window, activityConfigCallback);? //創(chuàng)建PhoneWindow斤寇,這是對window操作的一系列操作的封裝

?? mWindow.setWindowControllerCallback(this);

?? mWindow.setCallback(this); ? ? ? ? ? ? ? ? ?? //設(shè)置callback是這個activity,有window相關(guān)的變化可以通知到這個activity

?? mWindow.setOnWindowDismissedCallback(this);

?? mWindow.getLayoutInflater().setPrivateFactory(this);

?? if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {

? ? ?? mWindow.setSoftInputMode(info.softInputMode);

?? }

?? mUiThread = Thread.currentThread();

?? mMainThread = aThread;

?? mInstrumentation = instr;

?? mToken = token;

?? mIdent = ident;

?? mApplication = application;

?? mIntent = intent;

?? mReferrer = referrer;

?? mComponent = intent.getComponent();

?? mActivityInfo = info;

?? mTitle = title;

?? mParent = parent;

?? mEmbeddedID = id;


?? mWindow.setWindowManager( ? ? ? ? ? ?

? ? ? ? ?? (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),

? ? ? ? ?? mToken, mComponent.flattenToString(),

? ? ? ? ?? (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);

?? if (mParent != null) {

? ? ?? mWindow.setContainer(mParent.getWindow());

?? }

?? mWindowManager = mWindow.getWindowManager();

?? mCurrentConfig = config;

?? mWindow.setColorMode(info.colorMode);

}

? 在attach函數(shù)中拥褂,也會為ContextWrapper中的mBase對象賦值一個ContextImpl對象娘锁,我們這里也能猜想到Service的創(chuàng)建估計也會有這個過程,而事實上Service的創(chuàng)建差不多也是這個過程肿仑,所以不再贅述了致盟。


? ? 我們可以知道Context例的實例化都是在我們在Application,Activity和Service創(chuàng)建的時候會實例化尤慰,而這些組件的父類都是ContextWrapper馏锡,所以在創(chuàng)建的時候還會先創(chuàng)建一個ContextImpl類對象,然后給自己的父類mBase變量賦值伟端,既然如此杯道,Context的引用對應(yīng)的就是Application,Activity和Service了责蝠,Context的用處就是提供了一組抽象的函數(shù)党巾,讓子類去相對應(yīng)的實現(xiàn),當(dāng)你持有一個Context引用的時候霜医,你可以通過這個引用去獲取相對應(yīng)組件的信息齿拂。比如持有一個Activity的Context引用,你可以在別的地方調(diào)用startActivity()去啟動一個新的activity肴敛。

總結(jié):

? 1.Context是抽象類署海,所以實例化要在子類中吗购,Application,Service砸狞,Activity是我們實例化的地方捻勉,一般應(yīng)用創(chuàng)建會實例化一個Application類,Service和Activity則是在startService和StartActivity被調(diào)用的時候會實例化刀森,它們都會創(chuàng)建一個ContextImpl類實例踱启,給自己的父類ContextWrapper的mBase變量賦值。

? 2.Context是組件中通用操作的一組集合研底,當(dāng)具體的子類實例化后埠偿,可以在別的地方通過保存一個Context引用去獲取信息和通用操作等,也就是說飘哨,我們可以通過這個引用去獲取到這個應(yīng)用中的重要信息以及這個應(yīng)用的通用操作胚想。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市芽隆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌统屈,老刑警劉巖胚吁,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異愁憔,居然都是意外死亡腕扶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門吨掌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來半抱,“玉大人,你說我怎么就攤上這事膜宋×蓿” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵秋茫,是天一觀的道長史简。 經(jīng)常有香客問我,道長肛著,這世上最難降的妖魔是什么圆兵? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮枢贿,結(jié)果婚禮上殉农,老公的妹妹穿的比我還像新娘。我一直安慰自己局荚,他們只是感情好超凳,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般聪建。 火紅的嫁衣襯著肌膚如雪钙畔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天金麸,我揣著相機(jī)與錄音擎析,去河邊找鬼。 笑死挥下,一個胖子當(dāng)著我的面吹牛揍魂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播棚瘟,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼现斋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了偎蘸?” 一聲冷哼從身側(cè)響起庄蹋,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎迷雪,沒想到半個月后限书,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡章咧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年倦西,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赁严。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡扰柠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出疼约,到底是詐尸還是另有隱情卤档,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布忆谓,位于F島的核電站裆装,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏倡缠。R本人自食惡果不足惜哨免,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望昙沦。 院中可真熱鬧琢唾,春花似錦、人聲如沸盾饮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至普办,卻和暖如春工扎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背衔蹲。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工肢娘, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人舆驶。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓橱健,卻偏偏與公主長得像,于是被迫代替她去往敵國和親沙廉。 傳聞我的和親對象是個殘疾皇子拘荡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355