App啟動流程淺析(Android10)

一些可以了解的知識

和啟動流程相關的類

從這篇文章拿來的圖片

https://blog.csdn.net/zplxl99/article/details/104507480/

image.png
  1. ActivityTaskManagerService: 是Android 10新增加的系統(tǒng)服務類劳澄,可以看做幫AMS分攤工作的類
  2. ActivityStackSupervisor: 負責所有Activity棧的管理
  3. ActivityStack: 內部維護一個 TaskRecord隊列 用來保存TaskRecord
  4. TaskRecord: 內部維護一個 ActivityRecord隊列 用來保存ActivityRecord
  5. ActivityRecord: 代表一個activity充坑,保存了Activity的各種信息提供給AMS使用

Launcher啟動

  • 你的手機桌面就是一個Launcher進程,當你點擊桌面App時舌仍。他就會通過Binder通信(跨進程通信)去請求system_server進程啟動一個Activity
  • system_server進程是一個系統(tǒng)進程,里面基本存放了所有手機Service服務袱贮,其中管理我們App四大組件的AMS也在其中
  • 如果你的APP沒啟動過概而,AMS會請求Zygote進程去fork出你的App進程悯仙,這就是冷啟動
  • 如果你的APP啟動過了,已經(jīng)fork出來了想诅,那么就會直接啟動你的第一個Activity召庞,這就是熱啟動


    image.png

Application啟動流程

ActivityThread.java
從App進程被創(chuàng)建出來后,就會執(zhí)行Main函數(shù)
通過貼出的關鍵代碼来破,我們可以這樣整理一下

  • main函數(shù)創(chuàng)建出了一個ActivityThread實例篮灼,
  • 通過ActivityManager獲取到AMS實例代理
  • 調用AMS的方法attachApplication,請求創(chuàng)建綁定Application徘禁,并把ApplicationThread給AMS
===== ActivityThread.java =====
public static void main(String[] args) {
    ....
    // 創(chuàng)建出ActivityThread實例(注意這不是一個線程W缬铡!)
    ActivityThread thread = new ActivityThread();
    // 然后調用attach去做一些綁定
    thread.attach(false, startSeq);
    ....
}

==== 還是在ActivityThread.java ====
private void attach(boolean system, long startSeq) {
    // 注意這個變量送朱,就是把當前ActivityThread實例保存在當前類的sCurrentActivityThread變量中
    sCurrentActivityThread = this;
    // 上面?zhèn)魅氲氖莝ystem = FALSE娘荡,進入
    mSystemThread = system;
    if (!system) {
        ...
        // 拿到一個IActivityManager對象干旁,這里直接當做是AMS
        final IActivityManager mgr = ActivityManager.getService();
        try {
            // 重點方法,mgr(= AMS),也就是調用AMS的方法
            // 注意這里傳入的 mAppThread 變量
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        // 添加GC內存回收的一個箭筒炮沐,感興趣可以了解一下
        // Watch for getting close to heap limit.
        BinderInternal.addGcWatcher(new Runnable(){});
    } else {
        ....
    }
    ...
}

==== 還是在ActivityThread.java ====
通過搜索發(fā)現(xiàn)争群,mAppThread就是一個ApplicationThread實例,這個實例是ActivityThread的一個內部類
@UnsupportedAppUsage
final ApplicationThread mAppThread = new ApplicationThread();


ActivityManagerService.java

  • 給Binder通信賦pid,uid保證安全性
  • 回到ActivityThread的ApplicationThread大年,調用bindApplication
==== ActivityManagerService.java ====
public final void attachApplication(IApplicationThread thread, long startSeq) {
    if (thread == null) {
        throw new SecurityException("Invalid application interface");
    }
    synchronized (this) {
        // 這里每一句話都很重要
        // 但是根據(jù)流程我們會進入到4方法中去
        // Bindder通信安全换薄,自帶驗證信息就是在這里賦值的(1,2,4,5)也是Bindder安全的原因
        1.int callingPid = Binder.getCallingPid();
        2.final int callingUid = Binder.getCallingUid();
        3.final long origId = Binder.clearCallingIdentity();
        4.attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        5.Binder.restoreCallingIdentity(origId);
    }
}



==== 還是 ActivityManagerService.java ====
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
    ....
    // 這里的thread就是 mAppThread=ApplicationThread()
    // 所以調用了這個函數(shù)翔试,流程又會回到ActivityThread.java文件去
    thread.bindApplication(各種參數(shù))
    ....
     
    // 記住bindApplication執(zhí)行完畢后轻要,流程又會回到這邊來,這里先貼出代碼垦缅,混個眼熟冲泥,
    if (normalMode) {
        try {
            didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }
   
}

ActivityThread.java

  • bindApplication會發(fā)送一個Handler消息
  • 而處理這個消息的Handler也在ActivityThread中的Class H
  • H收到消息后就會開始執(zhí)行創(chuàng)建并綁定Application的操作
  • 并且在創(chuàng)建完Application后,還會初始化ContentProvide
=== 在ActivityThread.java中的內部類ApplicationThread中 ===
public final void bindApplication(String processName, ApplicationInfo appInfo,......){
    ....(給data設置各種參數(shù)值)
    
    // 發(fā)送一個Handler消息
    sendMessage(H.BIND_APPLICATION, data);
}




=== 在ActivityThread.java中的內部類H中 ===
class H extends Handler {

    public static final int BIND_APPLICATION        = 110;

    public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case BIND_APPLICATION:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                AppBindData data = (AppBindData)msg.obj;
                // 發(fā)送了消息之后在這里接收失都,然后綁定Application
                handleBindApplication(data);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
    }

}



=== 在ActivityThread.java中 ===
// 說實話這里比較抽象柏蘑,如果不查找資料的話,進去容易找不到粹庞,不知道看哪里然后出不來
private void handleBindApplication(AppBindData data) {
    // 創(chuàng)建Application
    app = data.info.makeApplication(data.restrictedBackupMode, null);
    // 賦值給本地變量
    mInitialApplication = app;

    // ContentProviders 初始化
    if (!data.restrictedBackupMode) {
        if (!ArrayUtils.isEmpty(data.providers)) {
            installContentProviders(app, data.providers);
        }
    }

    try {
        // 調用Application的onCreate方法
        // (方法點進去是有注釋表明這是調用Application的onCreate)
        mInstrumentation.callApplicationOnCreate(app);
    } catch (Exception e) {
        if (!mInstrumentation.onException(app, e)) {
            // 這里也可以看到咳焚,拋出的錯誤信息是無法創(chuàng)建Applicaiton
            throw new RuntimeException(
              "Unable to create application " + app.getClass().getName()
              + ": " + e.toString(), e);
        }
    }
}


==== 這里進入makeApplication()方法看一下 ====
public Application makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation) {
    // 創(chuàng)建context
    ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
    // 創(chuàng)建Application,并把上下文傳入
    app = mActivityThread.mInstrumentation.newApplication(
            cl, appClass, appContext);

    return app;
    
}

==== 這里進入newApplication()方法看一下 ====
public Application newApplication(ClassLoader cl, String className, Context context)
        throws InstantiationException, IllegalAccessException, 
        ClassNotFoundException {
    Application app = getFactory(context.getPackageName())
            .instantiateApplication(cl, className);
    // 這里最終會調用到attachBaseContext庞溜,所以這個方法在onCreate方法之前革半,并且還能拿到Context
    app.attach(context); --> attachBaseContext(context);
    return app;
}

Activity啟動流程

Application結束后,我們會回到ActivityManagerService.java流码,回到那個混臉熟的代碼塊那邊去

ActivityManagerService.java

  • 這里就是對Activity又官,Service,BroadCast的啟動
  • Activity的啟動會放在LocalService中去
==== ActivityManagerService.java ====
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,....){

    
    // See if the top visible activity is waiting to run in this process...
    if (normalMode) {
        try {
            // 這里雖然調用的方法是attachApplication漫试,但是他確實是Activity相關的
            // mAtmInternal 是 ActivityTaskManagerService中的內部類LocalService
            didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }
    
    // 這是Service
    // Find any services that should be running in this process...
    if (!badApp) {
        didSomething |= mServices.attachApplicationLocked(app, processName);
    }

    // 這是Broadcast
    // Check if a next-broadcast receiver is in this process...
    if (!badApp && isPendingBroadcastProcessLocked(pid)) {
        didSomething |= sendPendingBroadcastsLocked(app);
    }

}

ActivityTaskManagerService.java
這里是我感覺整個流程最抽象的地方了六敬,感覺需要配合WMS一起理解比較好

  • 這就是一系列調用流程,但是防止找不到就記錄下驾荣,反正最終會流入ActivityStackSupervisor.java
==== LocalService.java ====
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
    synchronized (mGlobalLockWithoutBoost) {
        if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);
        }
        try {
            // 這里會走整個方法
            // 這里沒什么說法外构,就是沒什么地方能進去,就走這個方法
            return mRootWindowContainer.attachApplication(wpc);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }
}

RootWindowContainer.java

==== RootWindowContainer.java ====
boolean attachApplication(WindowProcessController app) throws RemoteException {
    final PooledFunction c = PooledLambda.obtainFunction(
            // 這里繼續(xù)進入 startActivityForAttachedApplicationIfNeeded
            // 這里也沒什么說法播掷,就是看名字像就點進去看了
            RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,
            PooledLambda.__(ActivityRecord.class), app, stack.topRunningActivity());

}


==== 還是RootWindowContainer.java ====
private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
        WindowProcessController app, ActivityRecord top) {
    if (r.finishing || !r.okToShowLocked() || !r.visibleIgnoringKeyguard || r.app != null
            || app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) {
        return false;
    }

    try {
        // 這里繼續(xù)進入审编,會走到ActivityStackSupervisor.java
        if (mStackSupervisor.realStartActivityLocked(r, app, top == r /*andResume*/,
                true /*checkConfig*/)) {
            mTmpBoolean = true;
        }
    } catch (RemoteException e) {
        Slog.w(TAG, "Exception in new application when starting activity "
                + top.intent.getComponent().flattenToShortString(), e);
        mTmpRemoteException = e;
        return true;
    }
    return false;
}

ActivityStackSupervisor.java

  • 這里個人感覺這幾個點比較重要
  • clientTransaction,牢記這個玩意歧匈,因為他會一直一直一直傳遞下去
  • clientTransaction.addCallback(LaunchActivityItem) 簡單理解 用一個List存放LaunchActivityItem
  • clientTransaction.setLifecycleStateRequest(lifecycleItem) 簡單理解 存放下一個Activity要到的狀態(tài)
  • 最終走到ActivityThread的父類 ClientTransactionHandler 發(fā)送Handler消息
==== ActivityStackSupervisor.java ====
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
        boolean andResume, boolean checkConfig) throws RemoteException {

    // Create activity launch transaction.
    final ClientTransaction clientTransaction = ClientTransaction.obtain(
            proc.getThread(), r.appToken);
    
    // 創(chuàng)建初始的LaunchActivityItem垒酬,并把intent傳入,我們打開Activity使用的Intent也是這個
    // addCallback 就是添加當一個List中去,記住是把LaunchActivityItem添加到List中
    clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),....)

    // 創(chuàng)建一個與Activity生命周期相關的Item
    if (andResume) {
        lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
    } else {
        lifecycleItem = PauseActivityItem.obtain();
    }
    // 設置生命周期過程中勘究,下一步需要到達的哪個生命周期
    clientTransaction.setLifecycleStateRequest(lifecycleItem);

    // mService 是 ActivityTaskManagerService
    // getLifecycleManager() 是 ClientLifecycleManager
    // 記得這個clientTransaction進行了傳遞矮湘,他是有Activity信息的
    mService.getLifecycleManager().scheduleTransaction(clientTransaction);
   
}

ClientLifecycleManager.java

===== ClientLifecycleManager.java ====
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    final IApplicationThread client = transaction.getClient();
    // 這里又走到ClientTransaction.java中去
    transaction.schedule();
    ...
}

ClientTransaction.java

private IApplicationThread mClient;

public void schedule() throws RemoteException {
    // mClient == IApplicationThread
    // IApplicationThread == ApplicationThread == ActivityThread.java
    // 這個this就是上面的clientTransaction
    mClient.scheduleTransaction(this);
}

ActivityThread.java

private class ApplicationThread extends IApplicationThread.Stub {
    @Override
    public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        // 又調用ActivityThread的scheduleTransaction
        // 但是在ActivityThread中找不到這個方法
        // 找不到就看看父類
        // transaction == clientTransaction 繼續(xù)傳遞
        ActivityThread.this.scheduleTransaction(transaction);
    }
}

ClientTransactionHandler.java

public abstract class ClientTransactionHandler {
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        // 這里發(fā)送消息,有回到ActivityThread的Class H 中去了
        // clientTransaction最終是放到了msg.obj中
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
}

ActivityThread.java

// 這就看做是執(zhí)行各種生命周期Item的執(zhí)行器(我是這么理解的)
private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);

public void handleMessage(Message msg) {
    case EXECUTE_TRANSACTION:
        // 這里從msg中取出clientTransaction
        final ClientTransaction transaction = (ClientTransaction) msg.obj;
        // 接著execute執(zhí)行這個clientTransaction
        mTransactionExecutor.execute(transaction);
        if (isSystem()) {
            // Client transactions inside system process are recycled on the client side
            // instead of ClientLifecycleManager to avoid being cleared before this
            // message is handled.
            transaction.recycle();
        }
        // TODO(lifecycler): Recycle locally scheduled transactions.
        break;
}

TransactionExecutor.java

==== TransactionExecutor.java ====
public void execute(ClientTransaction transaction) {
    // transaction是啥?乱顾,是一直傳遞過來的clientTransaction
    ...
    // 循環(huán)遍歷回調請求的所有狀態(tài)并在適當?shù)臅r間執(zhí)行它們
    executeCallbacks(transaction);
    // 轉換到最終狀態(tài)
    executeLifecycleState(transaction);
    mPendingActions.clear();
    if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}


==== 還是TransactionExecutor.java ====

public void executeCallbacks(ClientTransaction transaction) {
    // transaction是啥?板祝,是一直傳遞過來的clientTransaction
    // getCallbacks是啥?走净,把addCallback對應方法券时,就是拿出存放了LaunchActivityItem的List
    final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
    final int size = callbacks.size();
    // 然后遍歷這個List
    for (int i = 0; i < size; ++i) {
        // 那么我們取出的第一個item,不就是LauncherActivityItem了嗎
        final ClientTransactionItem item = callbacks.get(i);
        
        if (closestPreExecutionState != UNDEFINED) {
            cycleToPath(r, closestPreExecutionState, transaction);
        }
        // 接著執(zhí)行LaunchActivityItem的方法
        item.execute(mTransactionHandler, token, mPendingActions);
        item.postExecute(mTransactionHandler, token, mPendingActions);
    }
}


==== 還是TransactionExecutor.java ====
// executeCallbacks 執(zhí)行完畢后就執(zhí)行 executeLifecycleState伏伯,這個方法比較簡單橘洞,就先說了
private void executeLifecycleState(ClientTransaction transaction) {
    // 獲取開始設置的 需要到達的 狀態(tài)
    // 從流程來看,現(xiàn)在這個就是 ResumeActivityItem
    final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
    ...
    // 接著就是ResumeActivityItem说搅,最終也就是 Activity.performResume()
    lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
    lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);

}

LaunchActivityItem.java

==== LaunchActivityItem.java ====
public void execute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    // Activity信息
    ActivityClientRecord r = new ActivityClientRecord(...);
    // client == ClientTransactionHandler == ActivityThread.java
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

ActivityThead.java

public Activity handleLaunchActivity(ActivityClientRecord r,...,Intent customIntent){
    // 這里返回拿到一個Activity炸枣,說明里面創(chuàng)建了Activity
    final Activity a = performLaunchActivity(r, customIntent);
}


private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 創(chuàng)建context
    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        // 類加載器
        java.lang.ClassLoader cl = appContext.getClassLoader();
        // 反射生成Activity
        activity = mInstrumentation.newActivity(
                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) {
        // 報錯信息也能看出,這是在創(chuàng)建Activity
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to instantiate activity " + component
                + ": " + e.toString(), e);
        }
    }
    
    ....
    // 綁定各種信息弄唧,可以自己進去看一看
    activity.attach(....)
    // 這里我也不知道走哪里适肠,但是不管哪個都是執(zhí)行 activity.performCreate()生命周期流程開始了
    if (r.isPersistable()) {
        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
    } else {
        mInstrumentation.callActivityOnCreate(activity, r.state);
    }
    
    // 設置成ON_CREATE
    r.setState(ON_CREATE);
}

然后Activity就這樣啟動了并走到了OnResume方法去了

總結一下

面試問到,說一下點擊Launcher的后候引,App啟動流程

  • Launcher進程請求AMS侯养,AMS請求Zygote進程,都是通過Binder通信的澄干,fork出我們的App
  • ActivityThread的main函數(shù)為入口逛揩,通過AMS實例的代理,幫助我們綁定Applicaiton(細節(jié)可自己補充)
  • 綁定完Applicaiton麸俘,對Activity對應的生命周期生成對應的item類辩稽,然后交給一個執(zhí)行器去執(zhí)行,每執(zhí)行一個item都會調用activity的方法从媚,然后又會推進到下一個生命周期的狀態(tài)

最后

這只是簡單的走一下流程逞泄,畢竟FrameWork層的東西,看多幾遍感覺還是懵的拜效,但是多看幾遍還是會有收獲的
而且里面還有很多細節(jié)炭懊,一些變量,包括和其他系統(tǒng)Service相關的東西拂檩,都是需要去想一想的,感覺也挺有意思的嘲碧。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末稻励,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌望抽,老刑警劉巖加矛,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異煤篙,居然都是意外死亡斟览,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門辑奈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苛茂,“玉大人,你說我怎么就攤上這事鸠窗〖搜颍” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵稍计,是天一觀的道長躁绸。 經(jīng)常有香客問我,道長臣嚣,這世上最難降的妖魔是什么净刮? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮硅则,結果婚禮上淹父,老公的妹妹穿的比我還像新娘。我一直安慰自己抢埋,他們只是感情好弹灭,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著揪垄,像睡著了一般穷吮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上饥努,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天捡鱼,我揣著相機與錄音,去河邊找鬼酷愧。 笑死驾诈,一個胖子當著我的面吹牛,可吹牛的內容都是我干的溶浴。 我是一名探鬼主播乍迄,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼士败!你這毒婦竟也來了闯两?” 一聲冷哼從身側響起褥伴,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎漾狼,沒想到半個月后重慢,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡逊躁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年似踱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稽煤。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡核芽,死狀恐怖,靈堂內的尸體忽然破棺而出念脯,到底是詐尸還是另有隱情狞洋,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布绿店,位于F島的核電站吉懊,受9級特大地震影響,放射性物質發(fā)生泄漏假勿。R本人自食惡果不足惜借嗽,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望转培。 院中可真熱鬧恶导,春花似錦、人聲如沸浸须。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽删窒。三九已至裂垦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肌索,已是汗流浹背蕉拢。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留诚亚,地道東北人晕换。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像站宗,于是被迫代替她去往敵國和親闸准。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內容