android 开发之activity 启动流程《三》

前言

前一篇介绍了在启动页面的时候创建进程的过程,当进程创建完成之后就会调用App的ActivityThread.main 方法。

一、mian

// ActivityThread类
public static void main(String[] args) {
     ... // 省略一些初始化代码

    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }

    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

我们通常说ActivityThread就是应用进程的主线程,这其实是一种笼统的说法,其实ActivityThread并非真正意义上的线程,它不是Thread的子类,只不过ActivityThread充当了主线程的职能,它初始化了一个消息队列。在ActivityThread对象构建时,会创建一个Handler对象,这个Handler对象所绑定的消息队列就是主线程的消息队列。ActivityThread对象构建后,会调用自身的attach()函数,发起一个绑定操作。

private void attach(boolean system) {
    // ...
    // 这里传进来的为false
    if (!system) {
// 设置进程名。此时,还没有ApplicationInfo,
//所以用<pre-initialized>来命名应用进程
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                        UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());

        final IActivityManager mgr = ActivityManager.getService();
        try {
            // 这里得到的对象为单例的ActivityManagerService对象
            // 因此我们直接转到ActivityManagerService中查看
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }else{
//
}
    // ...
}

mAppThread 是ThreadMain的成员变量,类型为ApplicationThread,是一个Binder类型, 后续AMS 会通过这个Bind 对象远程调用ThreadMain 的方法。

ActivityManagerService

    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }
IApplicationThread thread  就是ApplicationThread的一个客户端,可以看成是我们的App.
private final boolean attachApplicationLocked(IApplicationThread thread,
                                              int pid) {
    ProcessRecord app;

    // 根据PID映射应用进程的ProcessRecord对象
    //此时进程应该是创建好了
    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            app = mPidsSelfLocked.get(pid)
        }
    } else {
        app = null;
    }
    if (app == null) {
        // 获取ProcessRecord对象失败,则做一些清理操作后退出
        if (pid > 0 && pid != MY_PID) {
            Process.killProcessQuiet(pid)
        } else {
            thread.scheduleExit();
        }
        //返回失败
        return false;
    }

    if (app.thread != null) {
        // ProcessRecord对象之前绑定的进程还则,而当下需要将
        //ProcessRecord绑定到一个新的进程
        // 所以需要将之前ProcessRecord所绑定的进程信息清除
        handleAppDiedLocked(app, true, true);
    }

    final String processName = app.processName;
    try {
        // 注册应用进程的DeathRecipient,当应用进程崩溃时,
//系统进程可以收到通知
        AppDeathRecipient adr = new AppDeathRecipient(
                app, pid, thread);
        thread.asBinder().linkToDeath(adr, 0);
        app.deathRecipient = adr;
    } catch (RemoteException e) {
        app.resetPackageList(mProcessStats);
        startProcessLocked(app, "link fail", processName);
        return false;
    }

    // 将ProcessRecord对象绑定到应用进程,
// 这样ProcessRecord就变成了“激活”状态
//这样app就可以通过thread(实际是个binder) 互相联系.
//因为我们之前只是创建了一个进程,但是这个进程没有跟
//任何程序绑定,就是一个空的架子
    app.makeActive(thread, mProcessStats);
    app.curAdj = app.setAdj = -100;
    app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
    app.forcingToForeground = null;
    updateProcessForegroundLocked(app, false, false);
    app.hasShownUi = false;
    app.debugging = false;
    app.cached = false;
    app.killedByAm = false;

    mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

    boolean normalMode = mProcessesReady ||  isAllowedWhileBooting(app.info);
    // 获取应用进程的所有Provider
    //获取应用进程中所有注册的Provider,这需要通过PackageManager来扫描进程所关联的包名,所有静态的Provider信息,即ProviderInfo对象,都会保存到ProcessRecord.pubProviders变量中;
    List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;

    try {
    ... // 省略debug和性能相关的代码
        // 发起跨进程调用,将一堆的信息传递给应用进程
        // 在应用程序那里会创建对应的Application类
        thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                isRestrictedBackupMode || !normalMode, app.persistent,
                new Configuration(mConfiguration), app.compat,
                getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked());
        updateLruProcessLocked(app, false, null);
    } catch (Exception e) {...}

    mPersistentStartingProcesses.remove(app);
    mProcessesOnHold.remove(app);

    boolean badApp = false;
    boolean didSomething = false;
    if (normalMode) {
        try {
            // 调度Activity,比如打开某个页面,此时导致进程的创建
            //然后创建进程,创建之后继续打开之前想要打开的页面
            //realStartActivityLocked
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;
            }
        } catch (Exception e) {
            badApp = true;
        }
    }

    if (!badApp) {
        try {
            // 调度Service
            //同理,因为开启某个Service创建了这个进程,创建进程之后
            //才真正的开始开启这个Service
            //realStartServiceLocked
            didSomething |= mServices.attachApplicationLocked(app, processName);
        } catch (Exception e) {
            badApp = true;
        }
    }

    if (!badApp && isPendingBroadcastProcessLocked(pid)) {
        try {
            // 调度Broadcast
            didSomething |= sendPendingBroadcastsLocked(app);
        } catch (Exception e) {
            badApp = true;
        }
    }

    if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) {
    ... // 省略Backup相关的代码
    }

    if (badApp) {
        app.kill("error during init", true);
        handleAppDiedLocked(app, false, true);
        return false;
    }

    if (!didSomething) {
        updateOomAdjLocked();
    }

    return true;
}

该函数的实现逻辑如下:

1 获取之前创建的ProcessRecord对象。通过Binder.getCallingPid()可以获取Binder接口的调用者所在进程的PID 进一步,通过PID,就能获取到应用进程对应的ProcessRecord。如果ProcessRecord对象获取失败,则表示应用进程已经被杀掉,需要清除应用进程的数据;如果ProcessRecord之前所绑定的进程信息还在,则需要清除这些信息;

2 为应用进程注册AppDeathRecipient,它是存在于系统进程的对象,当应用进程被杀掉的时候,系统进程会收到通知;

3 激活ProcessRecord对象。所谓“激活”,就是ProcessRecord已经绑定到了一个应用进程,绑定的标识就是:应用进程的ApplicationThread对象赋值给ProcessRecord.thread变量;

4 获取应用进程中所有注册的Provider,这需要通过PackageManager来扫描进程所关联的包名,所有静态的Provider信息,即ProviderInfo对象,都会保存到ProcessRecord.pubProviders变量中;

5 进行一些调试与性能相关的变量设置之后,通过IApplicationThread.bindApplication()发起跨进程调用,这样一来,诸如进程名、ApplicationInfo等信息就传递给应用进程了;

6 将信息传递给应用程序以后,就可以进行调度了,mStackSupervisor.attachApplicationLocked(app)用于调度页面,mServices.attachApplicationLocked(app, processName)用于调度服务,sendPendingBroadcastsLocked用于调度广播。实际上这三个方法一般之后调用其中的一个。

下面先看看App端的bindApplication的实现

我们平常写项目中都会给项目指定一个Application类,该类也会拥有 onCreate() 等生命周期方法,而且Application的 onCreate 方法会比第一个Activity的onCreate() 方法优先执行,接下来我们从源码的角度来分析下为什么回是这样执行的


public final void bindApplication(
String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, 
ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection,
 int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, 
  Configuration config,
                CompatibilityInfo compatInfo, Map services, 
Bundle coreSettings,
                String buildSerial) {
        // ...
        // 这里发送了一个队列消息用于绑定Application
        // 这里的队列消息由 Handler 的子类 H 类发送,进入方法内部即可查看
        // H 类也是 ActivityThread 的内部类
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableOpenGlTrace = enableOpenGlTrace;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
//内部会创建Applicaton对象。
sendMessage(H.BIND_APPLICATION, data);
 }

handler 在收到BIND_APPLICATION消息的时候会调用handleBindApplication 方法




private void handleBindApplication(AppBindData data) {
... // 省略部分数据初始化代码

    // 虽然应用进程早就已经创建,但直到这时,才知道进程名是什么
//一般就是我们的包的名字
    Process.setArgV0(data.processName);
    android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId());

... // 省略部分进程运行信息设置代码

    // 创建应用进程的Android运行环境:Context
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    if (!Process.isIsolated()) {
    ... // 省略与缓冲目录设置相关的代码
    }

... // 省略应用进程相关的初始化代码,包含时区、StrictMode、
//调试模式等相关的设置

    // 根据情况初始化Intrumentation对象
    if (data.instrumentationName != null) {
    ...
        try {
            java.lang.ClassLoader cl = instrContext.getClassLoader();
            mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
        } catch (Exception e) { ... }

        mInstrumentation.init(this, instrContext, appContext,
                new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,
                data.instrumentationUiAutomationConnection);
    ...
    } else {
        mInstrumentation = new Instrumentation();
    }
...
    try {
        // 创建Application对象
        Application app = 
data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;
        // 装载Providers
        if (!data.restrictedBackupMode) {
            List<ProviderInfo> providers = data.providers;
            if (providers != null) {
                installContentProviders(app, providers);
            ...
            }
        }

        mInstrumentation.onCreate(data.instrumentationArgs);

        // 调用Application.onCreate()函数
        mInstrumentation.callApplicationOnCreate(app);
    }
...
}  

创建完对应的Application 之后AMS 就会开始调度,这里以调度某一个页面为例子也即是

执行mStackSupervisor.attachApplicationLocked(app)方法。

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    final String processName = app.processName;
    boolean didSomething = false;
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
        ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = stacks.get(stackNdx);
            if (!isFrontStack(stack)) {
                continue;
            }
            ActivityRecord hr = stack.topRunningActivityLocked(null);
            if (hr != null) {
                if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                        && processName.equals(hr.processName)) {
                    try {
                        if (realStartActivityLocked(hr, app, true, true)) {
                            didSomething = true;
                        }
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Exception in new application when starting activity "
                              + hr.intent.getComponent().flattenToShortString(), e);
                        throw e;
                    }
                }
            }
        }
    }
    if (!didSomething) {
        ensureActivitiesVisibleLocked(null, 0);
    }
    return didSomething;
}


遍历寻找所有ActivityStack和TaskRecord,对栈顶的ActivityRecord进行操作。这里其实就是需要启动应用进程中还未启动的Activity。hr.app == null 表示ActivityRecord 还没有绑定进程,这是判断该Activity还未启动的一个重要的条件。

realStartActivityLocked从其函数取名来看,是要动真格的了,什么才叫真正启动一个Activity呢? 我们可以理解为:调度Activity.onCreate()函数执行了,就算是真正启动Activity。

// ActivityStackSupervisor 类
final boolean realStartActivityLocked(ActivityRecord r, 
ProcessRecord app,boolean andResume, boolean checkConfig)  {
    // ...
//将ActivityRecord与ProcessRecord 绑定在一起
r.app = app;
app.waitingToKill = null;
r.launchCount++;
r.lastLaunchTime = SystemClock.uptimeMillis();
    try {
        // ...
        // 这里调用了 ApplicationThread
// 中的 scheduleLaunchActivity() 方法
  //ApplicationThread  是一个binder对象
        app.thread.scheduleLaunchActivity(
new Intent(r.intent), r.appToken,
                System.identityHashCode(r), r.info,
                mergedConfiguration.getGlobalConfiguration(),
                mergedConfiguration.getOverrideConfiguration(), r.compat,
                r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                r.persistentState, results, newIntents, !andResume,
                mService.isNextTransitionForward(), profilerInfo);
        // ...
    } catch (RemoteException e) { 
    }
    return true;
}

1 将ProcessRecord和ActivityRecord关联。ActivityRecord对象的app属性,就是ProcessRecord类型;标示这个Activity 所属的进程,也标示了这个页面被启动了。

2 跨进程调用IApplicationThread.scheduleLaunchActivity(),调度启动Activity。

3 调用AS.minimalResumeActivityLocked()来显示Activity。

下面我们进入App的scheduleLaunchActivity

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
        ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
        String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
        PersistableBundle persistentState, List<ResultInfo> pendingResults,
        List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,
        ProfilerInfo profilerInfo) {

    updateProcessState(procState, false);

    ActivityClientRecord r = new ActivityClientRecord();

    r.token = token;
    r.ident = ident;
    r.intent = intent;
    r.referrer = referrer;
    r.voiceInteractor = voiceInteractor;
    r.activityInfo = info;
    r.compatInfo = compatInfo;
    r.state = state;
    r.persistentState = persistentState;

    r.pendingResults = pendingResults;
    r.pendingIntents = pendingNewIntents;

    r.startsNotResumed = notResumed;
    r.isForward = isForward;

    r.profilerInfo = profilerInfo;

    updatePendingConfiguration(curConfig);


        //实际还是一个异步
    sendMessage(H.LAUNCH_ACTIVITY, r);
}

handler 将会调用handleLaunchActivity 处理该消息

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;

    if (r.profilerInfo != null) {
        mProfiler.setProfiler(r.profilerInfo);
        mProfiler.startProfiling();
    }

    // Make sure we are running with the most recent config.
    handleConfigurationChanged(null, null);

    if (localLOGV) Slog.v(
        TAG, "Handling launch of " + r);

    // Initialize before creating the activity
    WindowManagerGlobal.initialize();

      //通过一个反射创建一个Activity
//并且执行onCreate 以及onStart方法
    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        Bundle oldState = r.state;

//执行resume方法同时
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed);

        if (!r.activity.mFinished && r.startsNotResumed) {
        }
    } else {
        try {
            ActivityManagerNative.getDefault()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
        } catch (RemoteException ex) {
            // Ignore
        }
    }
}

在进行了一些参数设置后,便调用ActivityThread.performLaunchActivity()函数,初始化一个Activity。如果初始化成功,便调用ActivityThread.handleResumeActivity()来处理Activity进入显示状态时需要完成的操作;如果初始化失败,则发起跨进程调用IActivityManager.finishActivity(),来通报结束一个Activity的生命周期。

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

    ActivityInfo aInfo = r.activityInfo;
   xxx

    Activity activity = null;
    try {
   	//
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
       //内部还是反射创建
        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) {
        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) {
//
            Context appContext = createBaseContextForActivity(r, activity);
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
            Configuration config = new Configuration(mCompatConfiguration);

//最先执行attach
//这个方法很重要,相当于给创建的activity内部属性赋值.
            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);

            if (customIntent != null) {
                activity.mIntent = customIntent;
            }
            r.lastNonConfigurationInstances = null;
            activity.mStartedActivity = false;
            int theme = r.activityInfo.getThemeResource();
            if (theme != 0) {
/设置主题,主题是在attach之后
                activity.setTheme(theme);
            }

            activity.mCalled = false;
            if (r.isPersistable()) {
//调用onCraete
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }

            r.activity = activity;
            r.stopped = true;
            if (!r.activity.mFinished) {
                activity.performStart();
                r.stopped = false;
            }

    return activity;
}

final void handleResumeActivity(IBinder token,
                                boolean clearHide, boolean isForward, boolean reallyResume) {
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;

    // 实际执行应用进程一侧的Activity.onResume()
    ActivityClientRecord r = performResumeActivity(token, clearHide);
    if (r != null) {
    ... // 省略与WindownManager相关的窗口操作
        if (reallyResume) {
            // 通知系统进程,Activity已经处于Resumed状态
            ActivityManagerNative.getDefault().activityResumed(token);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值