Android四大组件之Activity(八)——新创建的进程:Activity组件和新创建的进程相关联

本文详细解析了Android应用进程中Activity与新创建进程的关联过程,包括注册到system_server、创建Application及初始化环境。首先,通过ActivityThread.main启动进程,接着创建Application对象,安装ContentProvider,最后执行Application的onCreate方法。整个流程涉及到AMS、LoadedApk、ContextImpl、Instrumentation等多个组件的交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、使用的是Android 7.1.2的源代码:

https://pan.baidu.com/s/1XcVD68cC_2wKtm8jJkdNQA
przv

2、感谢IT先森的系列博客:

Android应用进程创建流程大揭秘
Android四大组件之bindService源码实现详解
Android四大组件之Activity启动流程源码实现详解概要
Activity启动流程(一)发起端进程请求启动目标Activity
Activity启动流程(二)system_server进程处理启动Activity请求
Activity启动流程(三)-Activity Task调度算法复盘分析
Activity启动流程(四)-Pause前台显示Activity,Resume目标Activity
Activity启动流程(五)请求并创建目标Activity进程
Activity启动流程(六)注册目标Activity进程到system_server进程以及创建目标Activity进程Application
Activity启动流程(七)初始化目标Activity并执行相关生命周期流程

当Zygote创建完一个应用进程之后,得到的仅仅是一个可以运行的载体,但是,Android的四大组件还没有进入到这个新创建的进程之中。

当Zygote进程创建目标Activity进程之后,还需要创建一个运行环境Context,然后创建Application,然后再装载Provider等组件信息。

目标Activity所属的应用进程已经创建好了,接下来,包括如下流程:

  • 注册目标Activity所属进程到system_server
  • 为目标Activity所属进程创建Application实例对象

伪代码:

ATP.bindApplication()---> 
BinderProxy.transact() --->
BpBinder.transact()--->

binder驱动传输--->

JavaBBinder.onTransact()--->
ATN.onTransact()--->
ATN.bindApplication(...) --->
ApplicationThread.bindApplication(...) --->
ActivityThread.H.sendMessage(H.BIND_APPLICATION,...) --->
ActivityThread.handleBindApplication(...) --->
	data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);//创建LoadedApk
	final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);//构建ContextImpl
	final ClassLoader cl = instrContext.getClassLoader();
    mInstrumentation = (Instrumentation)
    cl.loadClass(data.instrumentationName.getClassName()).newInstance();//构建Instrumentation
    installContentProviders(app, data.providers);//安装ContentProvider
    mInstrumentation.callApplicationOnCreate(app);//调用Application的onCreate方法

一、注册(attach)目标Activity进程到system_server

问题:目标Activity进程是由AMS创建的,为什么还需要将其注册到system_server进程?
答:通过attach的Binder远程调用传递匿名Binder类IApplicationThread给AMS,然后AMS就可以通过上述的匿名Binder来继续对目标Activity进程的相关组件进行调度。

1、ActivityThread.main

  • 调用attach,向system_server发起一个绑定操作,告诉AMS进程启动完毕,可以进行其他事情了
  • 初始化应用进程的主线程的Looper,并开启loop消息循环
public static void main(String[] args) {
   
   
        ··· ···
        Environment.initForCurrentUser();
		··· ···
        Process.setArgV0("<pre-initialized>");
		//创建主线程Looper
        Looper.prepareMainLooper();
        //创建一个新的ActivityThread
        ActivityThread thread = new ActivityThread();
        //attach到系统进程
        thread.attach(false);

        if (sMainThreadHandler == null) {
   
   
            sMainThreadHandler = thread.getHandler();
        }
		//主线程进入循环状态
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

注意:
    ActivityThread就是应用程序的主线程,这种说法是笼统的,因为ActivityThread并非真正意义上的线程,它不是Thread的子类。在ActivityThread对象构建时,会创建一个Handler对象,这个Handler对象所绑定的消息队列就是主线程的消息队列,后面主线程所做的任何事情都是往Handler中发送消息来完成的,所以说Android系统是基于消息驱动的。主线程实现Looper,就是在new ActivityThread()时实现的,即在ActivityThread.main()中构造ActivityThread对象时初始化的Looper。

public final class ActivityThread {
   
   
	final Looper mLooper = Looper.myLooper();
    final H mH = new H();
    private class H extends Handler {
   
   
        public static final int LAUNCH_ACTIVITY         = 100;
        public static final int PAUSE_ACTIVITY          = 101;
        ···
    }
    ··· ···
     ActivityThread() {
   
   
        mResourcesManager = ResourcesManager.getInstance();
    }
    ··· ···
}

在构造函数初始化时,其上面的变量也都会初始化:

public class One {
   
   
	private class H{
   
   
		H(){
   
   
			System.out.println("One::H():::");
		}
	}
	H mH = new H();
	int a = 3;
	public One() {
   
   
		System.out.println("One::One():::" + a);
	}
}
public class Two {
   
   
	public static void main(String args[]) {
   
   
		One mOne = new One();	
	}
}

输出结果为:

One::H():::
One::One():::3


2、ActivityThread.attach

final ApplicationThread mAppThread = new ApplicationThread();

//system参数的作用是区别是system_server进程发起的绑定还是普通应用进程发起的绑定
//我们现在是子进程发起的绑定
 
 private void attach(boolean system) {
   
   
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
   
   
            //设置进程名。
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
   
   
                mgr.attachApplication(mAppThread);  //这里的mAppThread是一个匿名Binder实例
            } catch (RemoteException ex) {
   
   
                throw ex.rethrowFromSystemServer();
            }
  			··· ···
        } else {
   
   
            //系统进程走这里
		}
  }

上述流程中,通过AMP借助Binder调用AMS的方法attachApplication,注意这里传递的mAppThread是一个匿名Binder实例,因此可以作为跨进程传递的参数。这里的mAppThread对象存在于应用进程,但会被传递到系统进程,在系统进程看来,此时的mAppThread就是操作应用进程的一个通信工具。后续,系统进程system_server如果想要向应用进程发起跨进程调用,也都需要通过mAppThread这个对象来完成相关的调度。

AMP.attachApplication的调用逻辑:
在这里插入图片描述

3、AMS.attachApplication

 // [AMS]
    @Override
    public final void attachApplication(IApplicationThread thread) {
   
   
        synchronized (this) {
   
   
        	//获取调用进程端pid
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

调用attachApplicationLocked进行下一步的处理,此时多了个参数pid。

注意,在Android源码中带Locked的方法,一般都需要进行加锁操作

在attachApplicationLocked中,会根据pid映射应用进程的ProcessRecord对象,在Android四大组件之Activity(五)——AMS:针对新启动的Activity创建一个新的进程 中的AMS.startProcessLocked中会将通过Process.start生成的pid给put到mPidsSelfLocked中。

 // [AMS]
   private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
   
   


        ProcessRecord app;
        long startTime = SystemClock.uptimeMillis();
        /*
         	1、根据PID映射应用进程的ProcessRecord对象
         	那么此处的ProcessRecord是什么时候创建并加入到mPidsSelfLocked中的呢,这个在该系列博客的五中有详细描述
        */
        if (pid != MY_PID && pid >= 0) {
   
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值