Android之Context Activity和Service的Context創(chuàng)建流程

我們在前面已經知道activity和service的啟動流程涉枫,activity和service本質上也是一個Context對象文捶,在其啟動過程中會創(chuàng)建一個與之關聯(lián)的Context對象

1:Activity的Context創(chuàng)建流程

當我們在啟動activity的過程是調用的方法都是startActivity,我們知道這是一個跨進程的過程,涉及到binder調用框沟,在AMS端Activity是以ActivityRecord形式存在的晋修,被TaskRecord以棧的形式管理,在啟動activity的過程中會根據(jù)intent和flag信息為其找到合適的Stack和Task,我們都知道主線程俺孙,ActivityThread便是Android應用程序的主線程辣卒,它是有應用程序進程創(chuàng)建過程中由zyote進程反射調用的,在Activity啟動過程中會調用handleLaunchActivity來啟動一個activity, 在其內部會調用performLaunchActivity來完成Activity的啟動

1.1:handleLaunchActivity
 // Initialize before creating the activity
        if (!ThreadedRenderer.sRendererDisabled) {
            GraphicsEnvironment.earlyInitEGL();
        }
        WindowManagerGlobal.initialize();
        final Activity a = performLaunchActivity(r, customIntent);
        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            if (!r.activity.mFinished && pendingActions != null) {
                pendingActions.setOldState(r.state);
                pendingActions.setRestoreInstanceState(true);
                pendingActions.setCallOnPostCreate(true);
            }
        } else {
            // If there was an error, for any reason, tell the activity manager to stop us.
            try {
                ActivityManager.getService()
                        .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
1.2:performLaunchActivity的具體實現(xiàn)
 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);
        }
        ComponentName component = r.intent.getComponent();-------->intent中有沒有指定組件名稱
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }
        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }
        ContextImpl appContext = createBaseContextForActivity(r);------->為activity創(chuàng)建ContextImpl對象
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(--------->通過classLoader創(chuàng)建一個Activity對象
                    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);
            if (activity != null) {
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) {
                    config.updateFrom(r.overrideConfig);
                }
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                }
                appContext.setOuterContext(activity);----->將創(chuàng)建的activity對象和ContextImpl對象關聯(lián)起來
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);

1.3:Activity的attch方法

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);------>關聯(lián)ContextImpl對象
        mFragments.attachHost(null /*parent*/);
        mWindow = new PhoneWindow(this, window, activityConfigCallback);---->創(chuàng)建PhoneWindow對象
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);--------------------->將this也就是activity和PhoneWindow關聯(lián)起來
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
       ...................................................
    }

1.4:attachBaseContext的實現(xiàn)

    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(newBase);
        if (newBase != null) {
            newBase.setAutofillClient(this);
        }
    }

1.5:attachBaseContext

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(newBase);
}
protected void attachBaseContext(Context base) {
    if (mBase != null) {
        throw new IllegalStateException("Base context already set");
    }
    mBase = base;--------------->mBase的數(shù)據(jù)類型是Context
}

由于Activity是繼承ContextThemeWrapper睛榄,ContextThemeWrapper是ContextWrapper的子類荣茫,這樣便將上面的ContextImpl和Activity的成員變量mBase關聯(lián)起來了

2.Service的Context創(chuàng)建過程

service的context創(chuàng)建流程和activity的context創(chuàng)建流程大致上是一致的

        public final void scheduleCreateService(IBinder token,
                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
            updateProcessState(processState, false);
            CreateServiceData s = new CreateServiceData();
            s.token = token;
            s.info = info;
            s.compatInfo = compatInfo;
            sendMessage(H.CREATE_SERVICE, s);
        }

最終的方法是handleCreateService

private void handleCreateService(CreateServiceData data) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = packageInfo.getAppFactory()----------->創(chuàng)建一個service對象
                    .instantiateService(cl, data.info.name, data.intent);
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to instantiate service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);----->創(chuàng)建一個ContextImpl對象
            context.setOuterContext(service);------>將service對象和ContextImpl對象關聯(lián)起來
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());-------------------->調用attach方法
            service.onCreate();----------------------------------------->回調其生命周期
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

2.1service的attach方法實現(xiàn)

    public final void attach(
            Context context,
            ActivityThread thread, String className, IBinder token,
            Application application, Object activityManager) {
        attachBaseContext(context);----------------->關聯(lián)ContextImpl對象
        mThread = thread;           // NOTE:  unused - remove?
        mClassName = className;
        mToken = token;
        mApplication = application;
        mActivityManager = (IActivityManager)activityManager;
        mStartCompatibility = getApplicationInfo().targetSdkVersion
                < Build.VERSION_CODES.ECLAIR;
    }

這樣service的context對象便關聯(lián)和創(chuàng)建

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市场靴,隨后出現(xiàn)的幾起案子啡莉,更是在濱河造成了極大的恐慌,老刑警劉巖旨剥,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咧欣,死亡現(xiàn)場離奇詭異,居然都是意外死亡泞边,警方通過查閱死者的電腦和手機该押,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阵谚,“玉大人蚕礼,你說我怎么就攤上這事烟具。” “怎么了奠蹬?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵朝聋,是天一觀的道長。 經常有香客問我囤躁,道長冀痕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任狸演,我火速辦了婚禮言蛇,結果婚禮上,老公的妹妹穿的比我還像新娘宵距。我一直安慰自己腊尚,他們只是感情好,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布满哪。 她就那樣靜靜地躺著婿斥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪哨鸭。 梳的紋絲不亂的頭發(fā)上民宿,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機與錄音像鸡,去河邊找鬼活鹰。 笑死,一個胖子當著我的面吹牛只估,可吹牛的內容都是我干的华望。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼仅乓,長吁一口氣:“原來是場噩夢啊……” “哼赖舟!你這毒婦竟也來了?” 一聲冷哼從身側響起夸楣,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤宾抓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后豫喧,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體石洗,經...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年紧显,在試婚紗的時候發(fā)現(xiàn)自己被綠了讲衫。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖涉兽,靈堂內的尸體忽然破棺而出招驴,到底是詐尸還是另有隱情,我是刑警寧澤枷畏,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布别厘,位于F島的核電站,受9級特大地震影響拥诡,放射性物質發(fā)生泄漏触趴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一渴肉、第九天 我趴在偏房一處隱蔽的房頂上張望冗懦。 院中可真熱鬧,春花似錦仇祭、人聲如沸批狐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至承冰,卻和暖如春华弓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背困乒。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工寂屏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人娜搂。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓迁霎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親百宇。 傳聞我的和親對象是個殘疾皇子考廉,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內容