ActivityManagerService啟動(dòng)過(guò)程(基于android 8.0)

下邊這個(gè)圖是7.0 的


AMS類(lèi)的結(jié)構(gòu),copy自網(wǎng)絡(luò)

1.看得出AMS 實(shí)現(xiàn)了看門(mén)狗(Watchdog.Monitor)以及電量監(jiān)控(BatteryStatsImpl.BatteryCallback) 接口搅方,并且繼承了ActivityManagerNative
2.ActivityManagerNative實(shí)現(xiàn)了IActivityManager斋泄,使用Binder來(lái)跟應(yīng)用程序進(jìn)行通信涩馆,只不過(guò)這里AMN內(nèi)部增加了一個(gè)代理類(lèi)解藕真竖,最終其他進(jìn)程要跟AMS交互還是使用Binder機(jī)制钥飞。
這里很好玩的是8.0系統(tǒng)上ActivityManagerNative上已經(jīng)被delete

/**
 * {@hide}
 * @deprecated will be removed soon. See individual methods for alternatives.
 */
@Deprecated
public abstract class ActivityManagerNative

而且本身的AMS的繼承類(lèi)也相應(yīng)的變化了:

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback

這里的它的區(qū)別是繼承了IActivityManager.Stub 接口類(lèi)百框,了解Bindler機(jī)制的人應(yīng)該知道此處應(yīng)該是一個(gè)IActivityManager.aidl生成的java類(lèi)琳要。只不過(guò)這里android可能刪除了ActivityManagerNative這個(gè)類(lèi)寡具,并把一些Binder代碼轉(zhuǎn)化為了AIDL模版方式。
可以看下下邊兩個(gè)sdk中的代碼:
8.0上:
ActivityManagerNative.class中的代碼:

 /**
     * Retrieve the system's default/global activity manager.
     *
     * @deprecated use ActivityManager.getService instead.
     */
    static public IActivityManager getDefault() {
        return ActivityManager.getService();
    }

ActivityManager.class 中的代碼:

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

7.0上:
ActivityManagerNative.class中的代碼:

/**
*獲得IActivityManager類(lèi)
*/
static public IActivityManager getDefault() {
        return gDefault.get();
    }

static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
 
        return new ActivityManagerProxy(obj);

ActivityManager.class 中的代碼:

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);//注意這一行
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

可以看得出來(lái)稚补,兩個(gè)的寫(xiě)法不一樣童叠,本質(zhì)上都是一樣的,只不過(guò)這里android可能使用了統(tǒng)一的AIDL方式進(jìn)行ipc课幕,減少了代碼的維護(hù)厦坛。所以我們?cè)趯?xiě)ipc的時(shí)候還是使用aidl模版比較好,利于維護(hù)乍惊。

好了有點(diǎn)扯遠(yuǎn)了粪般,回到正題上AMS的啟動(dòng)過(guò)程:

AMS的啟動(dòng)是在SystemServer(系統(tǒng)進(jìn)程)中進(jìn)行啟動(dòng)的,我們知道android所有的進(jìn)程都是由zygote fork出來(lái)的污桦,SystemServer也不例外。下邊捋一下SystemServer的代碼:

SystemServer
/**
     * The main entry point from zygote.
     */
//很清楚看到是由zygote進(jìn)程fork來(lái)的
    public static void main(String[] args) {
        new SystemServer().run();
    }

run方法:

private void run() {
           ....
             (1)
            Looper.prepareMainLooper();

            // Initialize native services.
            System.loadLibrary("android_servers");
          ....
             (2)
            // Initialize the system context.
            createSystemContext();  
             (3)
            // Create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext); 
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
           ....
          (4) 
        // Start services.
        try {
            traceBeginAndSlog("StartServices");
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }
        ....
        // Loop forever.
        Looper.loop();
         (5)
        throw new RuntimeException("Main thread loop unexpectedly exited");
}
  • (1).Looper.prepareMainLooper();方法:

初始化MainLooper,這里可以看得出我們這個(gè)SystemServer本身可能就是一個(gè)應(yīng)用進(jìn)程匙监。
這里稍微擴(kuò)展一下Looper.prepareMainLooper()函數(shù)是創(chuàng)建了一個(gè)全局靜態(tài)的sMainLooper,創(chuàng)建函數(shù)是:

private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

1.這里我當(dāng)時(shí)沒(méi)想明白是怎么把ActivityThread跟Looper進(jìn)行綁定的凡橱,畢竟ActivityThread是在Looper初始化之后new的小作,而Looper的new過(guò)程是伴隨著綁定當(dāng)前線程的。這里我們一定要注意:
ActivityThread不是一個(gè)線程稼钩,盡管以此命名顾稀,我們new的ActivityThread只不過(guò)是一個(gè)普通類(lèi)。同時(shí)行使主線程的能力罷了坝撑。
2.這里的Looper是使用sThreadLocal保證全局唯一的静秆,ThreadLocal也是一個(gè)很有意思的類(lèi),它可以看作是一個(gè)Map的工具類(lèi)巡李,使用統(tǒng)一的工具類(lèi)管理各個(gè)分散在不同Thread中的ThreadLocalMap抚笔,以ThreadLocal為key,管理各個(gè)thread中map值侨拦,當(dāng)然這里必須使用弱引用防止內(nèi)存問(wèn)題殊橙。這種統(tǒng)一管理方式很值得學(xué)習(xí)。

  • (2)createSystemContext方法:

1.得到了一個(gè)ActivityThread對(duì)象狱从,它代表當(dāng)前進(jìn)程 (此時(shí)為系統(tǒng)進(jìn)程) 的主線程膨蛮;
2.得到了一個(gè)Context對(duì)象,對(duì)于SystemServer而言季研,它包含的Application運(yùn)行環(huán)境與framework-res.apk有關(guān)敞葛。

private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    }
public static ActivityThread systemMain() {
        // The system process on low-memory devices do not get to use hardware
        // accelerated drawing, since this can add too much overhead to the
        // process.
        if (!ActivityManager.isHighEndGfx()) {
            ThreadedRenderer.disable(true);
        } else {
            ThreadedRenderer.enableForegroundTrimming();
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(true);
        return thread;
    }
  • (3)創(chuàng)建SystemServiceManager,它會(huì)對(duì)系統(tǒng)的服務(wù)進(jìn)行創(chuàng)建与涡、啟動(dòng)和生命周期管理惹谐。
  • (5)throw new RuntimeException("Main thread loop unexpectedly exited");

這里一種防止Looper quit的一種方式

  • (4) 啟動(dòng)各種service,這里startBootstrapServices ()方法是初始化AMS的递沪,只需要看此方法即可
      private void startBootstrapServices() {
....
        Installer installer = mSystemServiceManager.startService(Installer.class);
....
        // Activity manager runs the show.
        //真正啟動(dòng)AMS的地方
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
....
// Set up the Application instance for the system process and get started. 
    //注冊(cè)一些系統(tǒng)服務(wù)
//將framework-res.apk的信息加入到SystemServer對(duì)應(yīng)的LoadedApk中豺鼻,
//同時(shí)構(gòu)建SystemServer進(jìn)程對(duì)應(yīng)的ProcessRecord, 以將SystemServer進(jìn)程納入到AMS的管理中款慨。
        mActivityManagerService.setSystemProcess();
....
    }

可以看出AMS是使用SystemServiceManager(SSM)啟動(dòng)的儒飒,SSM啟動(dòng)的service必須繼承自final Class<SystemService> serviceClass;,但是這里因?yàn)锳MS并不是,所以使用了ActivityManagerService.Lifecycle.class類(lèi)。

    public static final class Lifecycle extends SystemService {
        private final ActivityManagerService mService;

        public Lifecycle(Context context) {
            super(context);
            mService = new ActivityManagerService(context);
        }

        @Override
        public void onStart() {
            mService.start();
        }

        public ActivityManagerService getService() {
            return mService;
        }
    }

很簡(jiǎn)單這只不過(guò)是AMS 的代理類(lèi)檩奠,也是為了解藕桩了,這種啟動(dòng)Service的處理方式蠻特別的〔捍粒可以學(xué)習(xí)下SystemServiceManager的源碼井誉,這里不做深入。

這里L(fēng)ifecycle.class中有兩步操作 整胃,

  1. mService = new ActivityManagerService(context);
// Note: This method is invoked on the main thread but may need to attach various
    // handlers to other threads.  So take care to be explicit about the looper.
    public ActivityManagerService(Context systemContext) {
        ...
        mServices = new ActiveServices(this);
        mProviderMap = new ProviderMap(this);
        mAppErrors = new AppErrors(mUiContext, this);
        ...
        Watchdog.getInstance().addMonitor(this);
        Watchdog.getInstance().addThread(mHandler);
    }

可以看得出來(lái)AMS的構(gòu)造方法中都是一些初始化操作颗圣,以及增加了看門(mén)狗

  1. mService.start();
private void start() {
        //完成統(tǒng)計(jì)前的復(fù)位工作
        removeAllProcessGroups();
        //開(kāi)始監(jiān)控進(jìn)程的CPU使用情況
        mProcessCpuThread.start();
        //注冊(cè)服務(wù)
        mBatteryStatsService.publish(mContext);
        mAppOpsService.publish(mContext);
        Slog.d("AppOps", "AppOpsService published");
        LocalServices.addService(ActivityManagerInternal.class, new LocalService());
        // Wait for the synchronized block started in mProcessCpuThread,
        // so that any other acccess to mProcessCpuTracker from main thread
        // will be blocked during mProcessCpuTracker initialization.
        try {
            mProcessCpuInitLatch.await();
        } catch (InterruptedException e) {
            Slog.wtf(TAG, "Interrupted wait during start", e);
            Thread.currentThread().interrupt();
            throw new IllegalStateException("Interrupted wait during start");
        }
    }

主要處理了:
1、啟動(dòng)CPU監(jiān)控線程。該線程將會(huì)開(kāi)始統(tǒng)計(jì)不同進(jìn)程使用CPU的情況在岂。
2奔则、發(fā)布一些服務(wù),如BatteryStatsService蔽午、AppOpsService(權(quán)限管理相關(guān))和本地實(shí)現(xiàn)的繼承ActivityManagerInternal的服務(wù)易茬。

看上邊的startBootstrapServices方法中mActivityManagerService.setSystemProcess()方法

public void setSystemProcess() {
        try {
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(this));
            ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
            ServiceManager.addService("dbinfo", new DbBinder(this));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this));
            }
            ServiceManager.addService("permission", new PermissionController(this));
            ServiceManager.addService("processinfo", new ProcessInfoService(this));

            ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                    "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
            mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

            synchronized (this) {
                ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
                app.persistent = true;
                app.pid = MY_PID;
                app.maxAdj = ProcessList.SYSTEM_ADJ;
                app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
                synchronized (mPidsSelfLocked) {
                    mPidsSelfLocked.put(app.pid, app);
                }
                updateLruProcessLocked(app, false, null);
                updateOomAdjLocked();
            }
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(
                    "Unable to find android system package", e);
        }
    }

此方法中主要處理了
1、注冊(cè)一些服務(wù)及老;
2抽莱、獲取package名為“android”的應(yīng)用的ApplicationInfo;
3骄恶、調(diào)用ActivityThread的installSystemApplicationInfo食铐;
4、AMS進(jìn)程管理相關(guān)的操作叠蝇。

這里注意installSystemApplicationInfo ()方法:它主要處理了將package名為“android”的應(yīng)用的ApplicationInfo;(即framework-res.apk,資源apk)賦值給LoadedApk璃岳,這里不詳細(xì)拆分
SystemServer.run()startOtherServices();方法中有一類(lèi)似的代碼mActivityManagerService.installSystemProviders();此方法是加載運(yùn)行在SystemServer進(jìn)程中的ContentProvider,即SettingsProvider.apk (定義于frameworks/base/packages/SettingsProvider)悔捶。最終ContentProvider信息都將注冊(cè)到AMS中的mProviderMap集合中铃慷。

最后一步SystemSever#startOtherServices中調(diào)用ActivityManagerService#systemReady方法

public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) {
...
//通知一些服務(wù)可以進(jìn)行systemReady相關(guān)的工作,并進(jìn)行啟動(dòng)服務(wù)或應(yīng)用進(jìn)程的工作
...
//開(kāi)啟HomeActivity
startHomeActivityLocked(currentUserId, "systemReady");
...
}

到此我們的AMS已經(jīng)啟動(dòng)完全蜕该,后續(xù)是Activity的啟動(dòng)流程犁柜,這里不做講解。

鑒于時(shí)間限制堂淡,我就盜用下邊的流程圖作為總結(jié)吧馋缅。。绢淀。萤悴。


AMS的啟動(dòng)流程圖

其他:

  • AMS的通信機(jī)制:(使用AIDL)

APP向AMS發(fā)起進(jìn)程間通信:(IActivityManager.aidl)
ActivityManger.getService() 獲得AMS的Binder接口,在通過(guò)Stub.asInterface的方式皆的,轉(zhuǎn)成IActivityManager的接口覆履。然后就可以通過(guò)IActivityManager向AMS發(fā)起進(jìn)程間通信。

// android/app/Instrumentation.java
int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);

// android/app/ActivityManager.java
public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }
 
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

AMS向APP發(fā)起進(jìn)程間通信:(IApplication.aidl)
在AMS內(nèi)部持有每個(gè)ActivityThread的IApplication接口實(shí)例费薄,用時(shí)可以直接調(diào)用硝全。當(dāng)然這里也是Binder通信。
其實(shí)在ActivityThread.main()時(shí)會(huì)調(diào)用attach(bool)方法

private void attach(boolean system) {
      ...
        if (!system) {
           ...
            final IActivityManager mgr = ActivityManager.getService();
            try {
                //將IApplication注冊(cè)給AMS
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
           ...
    }
 @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
           ...
            attachApplicationLocked(thread, callingPid);
          ...  
        }
    }
private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
...
        updateLruProcessLocked(app, false, null);
...
 final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
            ProcessRecord client) {
...
        //AMS中 final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();
         mLruProcesses.add(app);
...

反正一系列的方法最后將IApplication傳遞到了AMS中楞抡,等到AMS調(diào)用APP時(shí)使用伟众。看下圖:


AMS跟應(yīng)用進(jìn)程通信
  • AMS本身運(yùn)行在SystemServer 中召廷,但同時(shí)也管理SystemServer(可以看作一個(gè)特殊APP)

  • SettingProvider.apk

SettingProvider.apk 給Settings應(yīng)用提供設(shè)置默認(rèn)值凳厢、設(shè)置存儲(chǔ)和設(shè)置修改服務(wù)账胧。其源碼在frameworks/base/packages目錄下。其apk在設(shè)備上的位置:/system/priv-app/SettingsProvider数初。本次對(duì)SettingProvider的修改主要針對(duì)一些設(shè)置默認(rèn)值

Framework-res.apk

系統(tǒng)默認(rèn)的一些資源信息

  • tag:AMS啟動(dòng)流程找爱,通信機(jī)制
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市泡孩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌寺谤,老刑警劉巖仑鸥,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異变屁,居然都是意外死亡眼俊,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)粟关,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)疮胖,“玉大人,你說(shuō)我怎么就攤上這事闷板∨炀模” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵遮晚,是天一觀的道長(zhǎng)性昭。 經(jīng)常有香客問(wèn)我,道長(zhǎng)县遣,這世上最難降的妖魔是什么糜颠? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮萧求,結(jié)果婚禮上其兴,老公的妹妹穿的比我還像新娘。我一直安慰自己夸政,他們只是感情好元旬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著秒梳,像睡著了一般法绵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上酪碘,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天朋譬,我揣著相機(jī)與錄音,去河邊找鬼兴垦。 笑死徙赢,一個(gè)胖子當(dāng)著我的面吹牛字柠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播狡赐,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼窑业,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了枕屉?” 一聲冷哼從身側(cè)響起常柄,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎搀擂,沒(méi)想到半個(gè)月后西潘,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哨颂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年喷市,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片威恼。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡品姓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出箫措,到底是詐尸還是另有隱情腹备,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布蒂破,位于F島的核電站馏谨,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏附迷。R本人自食惡果不足惜惧互,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望喇伯。 院中可真熱鬧喊儡,春花似錦、人聲如沸稻据。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)捻悯。三九已至匆赃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間今缚,已是汗流浹背算柳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留姓言,地道東北人瞬项。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓蔗蹋,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親囱淋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子猪杭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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

  • 面試必背 會(huì)舍棄、總結(jié)概括——根據(jù)我這些年面試和看面試題搜集過(guò)來(lái)的知識(shí)點(diǎn)匯總而來(lái) 建議根據(jù)我的寫(xiě)的面試應(yīng)對(duì)思路中的...
    luoyangzk閱讀 6,755評(píng)論 6 173
  • Zygote是什么妥衣?有什么作用皂吮? Android系統(tǒng)底層基于Linux Kernel, 當(dāng)Kernel啟動(dòng)過(guò)程會(huì)創(chuàng)...
    Mr槑閱讀 2,806評(píng)論 4 18
  • 2.1 Activity 2.1.1 Activity的生命周期全面分析 典型情況下的生命周期:在用戶參與的情況下...
    AndroidMaster閱讀 3,040評(píng)論 0 8
  • 連雨不知春去涮较,一晴方覺(jué)夏深。時(shí)光飛逝冈止,又進(jìn)入了夏季。每年的夏天候齿,都會(huì)有一群正值青春年少滿懷夢(mèng)想的少年熙暴,伏案疾書(shū),...
    哆啦A夢(mèng)最有愛(ài)閱讀 292評(píng)論 0 0
  • 1.需求: 中間列主題內(nèi)容優(yōu)先加載; 主題內(nèi)容寬度自適應(yīng),左右兩邊內(nèi)容寬度固定; 2.使用技術(shù): 浮...
    慕名66閱讀 173評(píng)論 0 0