Activity启动流程(Application->Activity)

本文详细剖析了Android应用的启动过程,从ActivityThread的main方法开始,讲解了如何找到并执行main方法,接着阐述了Application的创建和启动流程,包括ApplicationThread的attach、bindApplication以及Application的onCreate方法。然后,文章深入探讨了Activity的创建和启动,解释了如何通过Instrumentation创建Activity,最后总结了Activity的onCreate()方法调用。整个过程揭示了Android系统如何从底层到上层启动一个应用及其组件。

学习目标:

ps:注释还是要看的哈!
换一个角度解析Activity启动流程
之前我写过一篇从另一个角度查看activity的启动流程(从startActivity()入手),要是这篇没看懂,可以查看那篇文章,链接如下 带着你解读Android10.0启动流程源码.


学习内容:

首先问这样一个问题?你们认为APP启动有main方法吗?
有的,绝对有main方法,只是google封装的很好,接下来就来我就带你找找。其实你可以在ActivityThread发现这个main()方法。

//Activity实际上就是一个Handler 我们需要注意这一点
public final class ActivityThread extends ClientTransactionHandler {
   
   
  //与AMS通信的桥梁,作为服务端,接受AMS的操作然后执行。
  final ApplicationThread mAppThread = new ApplicationThread();
  //管理Application/Activity生命周期
  Instrumentation mInstrumentation;
  //主线成轮询
 private static Looper sMainLooper;
......

//主方法
 public static void main(String[] args) {
   
   
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        // Install selective syscall interception
        AndroidOs.install();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        // Call per-process mainline module initialization.
        initializeMainlineModules();

        Process.setArgV0("<pre-initialized>");
        
		/*************************轮询消息QUEUE******************************/
		
		//初始化Handler中的Looper对象。
        Looper.prepareMainLooper();

        // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
        // It will be in the format "seq=114"
        long startSeq = 0;
        if (args != null) {
   
   
            for (int i = args.length - 1; i >= 0; --i) {
   
   
                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
   
   
                    startSeq = Long.parseLong(
                            args[i].substring(PROC_START_SEQ_IDENT.length()));
                }
            }
        }
        //创建一个ActivityThread
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);
		//初始化专门处理消息的handler对象
        if (sMainThreadHandler == null) {
   
   
            sMainThreadHandler = thread.getHandler();
        }

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

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();
        
		/*************************轮询消息QUEUE******************************/
		
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
.....
   //这个方法就是我们使用handler时想要在主线程创建的时候会调用的方法
   //这就就是了为什么我们能通过Looper.getMainLooper()获取到主线程的原因
   public static Looper getMainLooper() {
   
   
        synchronized (Looper.class) {
   
   
            return sMainLooper;
        }
    }
     @Deprecated
    public static void prepareMainLooper() {
   
   
    	//false 当前looper不能手动退出
    	//true 相反
        prepare(false);
        synchronized (Looper.class) {
   
   
            if (sMainLooper != null) {
   
   
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            //myLooper():创建一个looper
            sMainLooper = myLooper();
        }
    }
  //AIDL跨进程通信
  //这个类通过Binder传到AMS中
  private class ApplicationThread extends IApplicationThread.Stub {
   
   
  	......
  }
}

前期工作做完了,我们就来说一下,当我们启动APP的时候肯定会先启动一个ApplicationThread,然后再启动一个Activity,所以我们接下来就细细地来看。
创建和启动Application

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

这两句代码调用的如下代码:

 private void attach(boolean system, long startSeq) {
   
   
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
   
   
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            //获取到AMS代理对象 IActivityManager,具体实现类是ActivityManagerService
            final IActivityManager mgr = ActivityManager.getService();
            try {
   
   
            	//所以这里实际调用的是ActivityManagerService.attachApplication()
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
   
   
                throw ex.rethrowFromSystemServer();
            }
            // Watch for getting close to heap limit.
            BinderInternal.addGcWatcher(new Runnable() {
   
   
                @Override public void run() {
   
   
                    if (!mSomeActivitiesChanged) {
   
   
                        return;
                    }
                    Runtime runtime = Runtime.getRuntime();
                    long dalvikMax = runtime.maxMemory();
                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                    if (dalvikUsed > ((3*dalvikMax)/4)) {
   
   
                        if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                                + " total=" + (runtime.totalMemory()/1024)
                                + " used=" + (dalvikUsed/1024));
                        mSomeActivitiesChanged = false;
                        try {
   
   
                            ActivityTaskManager.getService().releaseSomeActivities(mAppThread);
                        } catch (RemoteException e) {
   
   
                            throw e.rethrowFromSystemServer();
                        }
                    }
                }
            });
        } else {
   
   
            // Don't set application object here -- if the system crashes,
            // we can't display an alert, we just want to die die die.
            android.ddm.DdmHandleAppName.setAppName("system_process",
                    UserHandle.myUserId());
            try {
   
   
                mInstrumentation = new Instrumentation();
                mInstrumentation.basicInit(this);
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } catch (Exception e) {
   
   
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }

        ViewRootImpl.ConfigChangedCallback configChangedCallback
                = (Configuration globalConfig) -> {
   
   
            synchronized (mResourcesManager) {
   
   
                // TODO (b/135719017): Temporary log for debugging IME service.
                if (Build.IS_DEBUGGABLE && mHasImeComponent) {
   
   
                    Log.d(TAG, "ViewRootImpl.ConfigChangedCallback for IME, "
                            + "config=" + globalConfig);
                }

                // We need to apply this change to the resources immediately, because upon returning
                // the view hierarchy will be informed about it.
                if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
                        null /* compat */)) {
   
   
                    updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                            mResourcesManager.getConfiguration().getLocales());

                    // This actually changed the resources! Tell everyone about it.
                    if (mPendingConfiguration == null
                            || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
   
   
                        mPendingConfiguration = globalConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
                    }
                }
            }
        };
        ViewRootImpl.addConfigCallback(configChangedCallback);
    }

ActivityManagerService

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
   
   
	@Override
    public final void attachApplication(IApplicationThread thread, long startSeq) {
   
   
        if (thread == null) {
   
   
            throw new SecurityException("Invalid application interface");
        }
        synchronized (this) {
   
   
        	//当前进程的pid
            int callingPid = Binder.getCallingPid();
            //当前进程的uid
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
            Binder.restoreCallingIdentity(origId);
        }
    }
    ......
    private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
   
   

        // Find the application record that is being attached...  either via
        // the pid if we are running in multiple processes, or just pull the
        // next app record if we are emulating process with anonymous threads.
        // ProcessRecord  进程的记录者,相当于数据类
        ProcessRecord app;
       .............
            if (mPlatformCompat != null) {
   
   
                mPlatformCompat.resetReporting(app.info);
            }
            final ProviderInfoList providerList = ProviderInfoList.fromList(providers);
            if (app.isolatedEntryPoint != null) {
   
   
                // This is an isolated process which should just call an entry point instead of
                // being bound to an application.
                thread.runIsolatedEntryPoint(app
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值