欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文帶你看懂Android Application啟動(dòng)流程是怎樣的

 更新時(shí)間:2021年10月20日 09:43:26   作者:冬天的毛毛雨  
談到Android Application的啟動(dòng)流程,很多文章都是各種源碼類和方法的一堆調(diào)用關(guān)系,這樣的文章就算看一百遍,也只是云里霧里。源碼得看,但是最好不要一下子深陷到源碼的細(xì)節(jié)之中,不可自拔。這里站在前人的基礎(chǔ)之上做一個(gè)總結(jié)

基于Android11-API30

總覽

  • 獲取applicationThread,AMS這兩個(gè)Binder2.attach時(shí),將獲取applicationThread對(duì)象也傳遞到AMS進(jìn)程,請(qǐng)求遠(yuǎn)程調(diào)用通知AMS應(yīng)用進(jìn)程想要?jiǎng)?chuàng)建Application,此時(shí)AMS為服務(wù)端
  • AMS收到消息,請(qǐng)求調(diào)用applicationThread的遠(yuǎn)程接口,此時(shí)AMS為客戶端
  • applicationThread收到AMS的請(qǐng)求,通過Handler發(fā)起創(chuàng)建Application的處理任務(wù),后面就沒有遠(yuǎn)程接口調(diào)用了
  • 通過反射創(chuàng)建Application的實(shí)例,通過Instrumentation啟動(dòng)Application的onCreate方法

詳細(xì)流程分析

從 ActivityThread.java 的main方法開始看;

public static void main(String[] args) {
    ...
    ActivityThread thread = new ActivityThread();
    thread.attach(system=false, startSeq);//1
    ...
}

進(jìn)入attach方法;

if(!system){
    final IActivityManager mgr = ActivityManager.getService();
    try {
        mgr.attachApplication(mAppThread, startSeq);//1
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}

非系統(tǒng)應(yīng)用流程,根據(jù) getSeervice和捕獲的RemoteException可以斷定,此處在使用Binder進(jìn)行遠(yuǎn)程接口調(diào)用。
轉(zhuǎn)身看下mAppThread是什么?

final ApplicationThread mAppThread = new ApplicationThread();

private class ApplicationThread extends IApplicationThread.Stub {
    //批量的schedule*接口,比如scheduleReceiver、scheduleCreateService等
    public final void schedule*
    
    //TODO 關(guān)鍵方法
    public final void bindApplication(some args){}//1
    
    //一堆dump方法,比如dumpMemory、dumpActivity等
    
}

可以看到,ApplicationThread是一個(gè)實(shí)現(xiàn)了遠(yuǎn)程接口的Binder客戶端,內(nèi)部封裝實(shí)現(xiàn)了很多遠(yuǎn)程接口。不過這個(gè)客戶端什么時(shí)候連接的服務(wù)器還未可知,沒有找到bindService關(guān)鍵字,反正此時(shí)應(yīng)該已經(jīng)連接上對(duì)應(yīng)的Service了。應(yīng)該是在RuntimeInit.java類中進(jìn)行應(yīng)用進(jìn)程啟動(dòng)時(shí)啟動(dòng)的。

回來看下前一步服務(wù)的實(shí)例IActivityManager.attachApplication()內(nèi)部的實(shí)現(xiàn)。

先獲取AMS的實(shí)例,此處獲取AMS實(shí)例代碼跟Activity啟動(dòng)流程中一致

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的Binder后,繼續(xù)查看ActivityManagerService.java中的attachApplication方法

public final void attachApplication(IApplicationThread thread, long startSeq) {
    
   	synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq); //1
        Binder.restoreCallingIdentity(origId);
    }
}

單例獲取AMS實(shí)例,AMS服務(wù)在系統(tǒng)啟動(dòng)就已經(jīng)注冊到ServiceManager了,此處直接去獲取Binder實(shí)例就行,ServiceManager以Binder池的方式管理注冊的Server。

AMS的attachApplication方法中進(jìn)入到attachApplicationLocked方法,撿能看懂的代碼看,跟著thread參數(shù)查看代碼。

private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {

    try {
        AppDeathRecipient adr = new AppDeathRecipient(
                app, pid, thread);
        thread.asBinder().linkToDeath(adr, 0);//1
        app.deathRecipient = adr;
    } catch (RemoteException e) {
        app.resetPackageList(mProcessStats);
        mProcessList.startProcessLocked(app,
                new HostingRecord("link fail", processName),
                ZYGOTE_POLICY_FLAG_EMPTY);
        return false;
    }

    final ActiveInstrumentation instr2 = app.getActiveInstrumentation();

    if (instr2 != null) {//2
        thread.bindApplication(processName, appInfo, providerList,
                instr2.mClass,
                profilerInfo, instr2.mArguments,
                instr2.mWatcher,
                instr2.mUiAutomationConnection, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.compat, getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions,
                app.mDisabledCompatChanges);
    } else {
        thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
                null, null, null, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.compat, getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions,
                app.mDisabledCompatChanges);
    }

}

先給ApplicationThread這個(gè)Binder上個(gè)死亡代理,根據(jù)這個(gè)死亡代理應(yīng)該可以找到對(duì)應(yīng)的Service是如何重新啟動(dòng)的,感興趣可以繼續(xù)深入,咱們繼續(xù)往下走。
此處調(diào)用到thread.bindApplication接口,前面咱們查看ApplicationThread時(shí)有看到,直接切入。

private class ApplicationThread extends IApplicationThread.Stub {
    //批量的schedule*接口,比如scheduleReceiver、scheduleCreateService等
    public final void schedule*
    
    //TODO 關(guān)鍵方法
    public final void bindApplication(some args){
        AppBindData data = new AppBindData();
        ...一堆參數(shù)
        sendMessage(H.BIND_APPLICATION, data);//1
    }
    
    //一堆dump方法,比如dumpMemory、dumpActivity等
    
}

到達(dá)咱們Android開發(fā)工程師比較熟悉的點(diǎn)了,封裝了一堆參數(shù)后,通過H這個(gè)Handler對(duì)象發(fā)了一條BIND_APPLICATION消息,咱們看看這條消息去哪了,直接跟進(jìn)BIND_APPLICATION這個(gè)消息的捕捉位置。

//消息分發(fā)
class H extends Handler{
    public void handleMessage(Message msg){
        swich(msg.what){
            case BIND_APPLICATION: 
                AppBindData data = (AppBindData)msg.obj;
                handleBindApplication(data);//1
                break;
            ...省略
        }
    }
}

進(jìn)入消息分發(fā)處理方法,這個(gè)方法比較長,注意閱讀能看懂的代碼,不求甚解,跟蹤data的處理。

private void handleBindApplication(AppBindData data) {
    //各種初始化,比如進(jìn)程名,應(yīng)用名,AsyncTask線程池的配置,時(shí)區(qū),網(wǎng)絡(luò)發(fā)現(xiàn)
    
    //Context的初始化
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    
    try {
        final ClassLoader cl = instrContext.getClassLoader();
        mInstrumentation = (Instrumentation)//1
            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,//1
            data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
            
    ...
    Application app;
    app = data.info.makeApplication(data.restrictedBackupMode, null);//2

    mInstrumentation.onCreate(data.instrumentationArgs);
    mInstrumentation.callApplicationOnCreate(app);//3
}

通過反射實(shí)例化mInstrumentation對(duì)象,該對(duì)象為Android系統(tǒng)組件的管家,目前看可以控制Application和Activity的生命周期。

創(chuàng)建Application對(duì)象,進(jìn)去看下創(chuàng)建的代碼

//LoadApk.java #makeApplication
public Application makeApplication(boolean forceDefaultAppClass,
    Instrumentation instrumentation){
    ...
    app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);//1
    appContext.setOuterContext(app);
    ...
}

//Instrumentation.java #newApplication
public Application newApplication(ClassLoader cl, String className, Context context)
        throws InstantiationException, IllegalAccessException, 
        ClassNotFoundException {
    Application app = getFactory(context.getPackageName())
            .instantiateApplication(cl, className);//2
    app.attach(context);//首先回調(diào)attachBaseContext方法
    return app;
}

//AppComponentFactory #instantiateApplication
public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
        @NonNull String className)
        throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    return (Application) cl.loadClass(className).newInstance();//3
}

可以看出最后還是通過反射初始化了Application。

最后通過mInstrumentation對(duì)象完成Application類的onCreate方法的調(diào)用。

mInstrumentation.callApplicationOnCreate(app);//1

//Instrumentation.java #callApplicationOnCreate
public void callApplicationOnCreate(Application app) {
    app.onCreate();
}

到此這篇關(guān)于一文帶你看懂Android Application啟動(dòng)流程是怎樣的的文章就介紹到這了,更多相關(guān)Android Application 啟動(dòng)流程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論