美文网首页
Android 应用启动那些事儿,Application? C

Android 应用启动那些事儿,Application? C

作者: 张小凡凡 | 来源:发表于2019-07-29 13:06 被阅读0次

    本文主要总结梳理一下,应用进程启动, 以及应用中各种Context那些事儿,如有错误,欢迎指出~

    一,应用进程创建

    1,zygote创建新进程

    Android 应用程序不能主动开启一个进程,只能被动开启进程。在Mainfest注册四大组件时,可以指定运行的进程。在启动该组件时,AMS首先会判断该进程 是否已存在,如果不存在,则首先请求zygote进程创建该进程。

            <service android:name=".ServiceName"
                android:process=":processName"/>
    

    以启动一个服务为例,程序会先调用ActivityManagerService 中的startService()方法,在该方法内部会调用到ActiveService的bringUpServiceLocked方法 启动服务。

    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
                boolean whileRestarting, boolean permissionsReviewRequired)
                throws TransactionTooLargeException {
              ......
                app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
                if (app != null && app.thread != null) {
                   app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                   realStartServiceLocked(r, app, execInFg);
                   return null;
                }
    
              if (app == null && !permissionsReviewRequired) {
                if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                        hostingType, r.name, false, isolated, false)) == null) {
                    bringDownServiceLocked(r);
                    return msg;
                }
             }
    
            if (!mPendingServices.contains(r)) {
                mPendingServices.add(r);
            }
            return null;
        }
    

    mAm.getProcessRecordLocked()方法 用于判断当前进程是否已经存在,若不存在,则调用ActivityManagerService的startProcessLocked方法创建一个进程。最终会调用到Process的start方法。会请求zygote进程创建一个进程。

        public static final ProcessStartResult start(...) {
            return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                        runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                        abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
        }
    

    ZygoteProcess封装了与zygote进程相关的socket通信。zygote进程创建一个新进程后,会将该新进程的pid 返回当前系统进程中。

        @GuardedBy("mLock")
        private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
                ZygoteState zygoteState, ArrayList<String> args)
                throws ZygoteStartFailedEx {
            try {
                ......
                result.pid = inputStream.readInt();
                result.usingWrapper = inputStream.readBoolean();
    
                if (result.pid < 0) {
                    throw new ZygoteStartFailedEx("fork() failed");
                }
                return result;
            } catch (IOException ex) {
                zygoteState.close();
                throw new ZygoteStartFailedEx(ex);
            }
        }
    

    2,新进程向AMS发布IBinder实体对象

    新进程启动后,首先会执行ActivityThread.main函数,在 thread.attach()方法中会通过Binder机制调用AMS的attachApplication方法,实际上就是通知AMS 新进程已创建好,并将自己的IBinder发布到AMS中。

    public static void main(String[] args) {
            .....
            Looper.prepareMainLooper();
    
            ActivityThread thread = new ActivityThread();
            thread.attach(false, startSeq);
    
            Looper.loop();
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }
    
    private void attach(boolean system, long startSeq) {
            sCurrentActivityThread = this;
            mSystemThread = system;
            if (!system) {
                 .....
                RuntimeInit.setApplicationObject(mAppThread.asBinder());
                final IActivityManager mgr = ActivityManager.getService();
                try {
                    mgr.attachApplication(mAppThread, startSeq);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
                  .....
        }
    

    3,创建新进程Application对象

    当应用进程启动,并向AMS发布自己的IBinder实体对象后,AMS 调用attachApplication()方法创建应用的Application对象。其中,thread为应用进程在AMS进程的binder对象。

       @Override
        public final void attachApplication(IApplicationThread thread, long startSeq) {
            synchronized (this) {
                attachApplicationLocked(thread, callingPid, callingUid, startSeq);
            }
        }
    
    @GuardedBy("this")
     private final boolean attachApplicationLocked(IApplicationThread thread,
                int pid, int callingUid, long startSeq) {
           .....
           thread.bindApplication(...)
           ......
           return true;
        }
    

    bindApplication()方法在应用进程的Binder线程中执行。 首先会封装app数据到AppBindData,然后发送Handler消息,在主线程中执行handleBindApplication()方法。

            public final void bindApplication(...) {
                AppBindData data = new AppBindData();
                .....
                sendMessage(H.BIND_APPLICATION, data);
            }
    
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case BIND_APPLICATION:
                        AppBindData data = (AppBindData)msg.obj;
                        handleBindApplication(data);
                        break;
    
        private void handleBindApplication(AppBindData data) {
    
             //初始化应用程序 基本数据
             ......
            Application app;   
            //创建Appcalition对象
            app = data.info.makeApplication(data.restrictedBackupMode, null);
             ......
             //调用Application.onCreate()方法
             mInstrumentation.callApplicationOnCreate(app);
            ......
        }
    

    通过调用Instrumentation 中的newApplication()方法,通过反射创建Application对象,并调用
    Application.attach(Context)生命周期回调方法

        public Application newApplication(ClassLoader cl, String className, Context context)
                throws InstantiationException, IllegalAccessException, 
                ClassNotFoundException {
            Application app = getFactory(context.getPackageName())
                    .instantiateApplication(cl, className);
            app.attach(context);
            return app;
        }
    

    至此完成Application的创建工作,由此也可得出,Application并不是与应用相对应,而是与应用进程一一对应。

    4,创建service实例

    AMS最终会同过Binder机制通知 刚刚创建的进程创建服务类实例,并调用服务相关的生命周期函数。

     private void handleCreateService(CreateServiceData data) {
            LoadedApk packageInfo = getPackageInfoNoCheck(
                    data.info.applicationInfo, data.compatInfo);
            Service service = null;
    
           java.lang.ClassLoader cl = packageInfo.getClassLoader();
           service = packageInfo.getAppFactory()
                        .instantiateService(cl, data.info.name, data.intent);
     
           ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
           context.setOuterContext(service);
    
           Application app = packageInfo.makeApplication(false, mInstrumentation);
           service.attach(context, this, data.info.name, data.token, app,
                        ActivityManager.getService());
           service.onCreate();          
        }
    

    二,各种Context

    1,简介

    Context是提供应用程序上下文的一个抽象类,可以用来访问系统资源,系统服务等等。

    public abstract class Context {
        public abstract Resources getResources();
        public abstract Context getApplicationContext();
        public abstract String getSystemServiceName(Class<?> serviceClass);
        public abstract void startActivity( Intent intent);
        public abstract ComponentName startService(Intent service);
    }
    

    ContextWrapper 是Context的实现类,同时接收一个ContextImp 对象 做静态代理。

    public class ContextWrapper extends Context {
        Context mBase;
        public ContextWrapper(Context base) {
            mBase = base;
        }
       
        protected void attachBaseContext(Context base) {
            if (mBase != null) {
                throw new IllegalStateException("Base context already set");
            }
            mBase = base;
        }
    
        public Context getBaseContext() {
            return mBase;
        }
    ...
    }
    

    ContextImpl 实现Context, 完成具体操作

    class ContextImpl extends Context {
     ....
    }
    

    2, Application 中的Context

    Applicaiton继承ContextWrapper, 具有保存应用进程内的全局变量、初始化操作、提供应用上下文的作用。

    public class Application extends ContextWrapper implements ComponentCallbacks2 {
          ...
        public Application() {
            super(null);
        }
         final void attach(Context context) {
            attachBaseContext(context);
        }
        public void onCreate() {
        }
    }
    

    应用程序创建Application, 并创建ContextImp对象通过attch赋值给mBase

    public Application makeApplication(...){
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
    }
    
        public Application newApplication(ClassLoader cl, String className, Context context) {
            Application app = getFactory(context.getPackageName())
                    .instantiateApplication(cl, className);
            app.attach(context);
            return app;
        }
    

    3, Activity 中的Context

    Activity继承ContextThemeWrapper类,而 ContextThemeWrapper继承ContextWrapper,只是封装了主题相关内容。

    public class Activity extends ContextThemeWrapper{
        ......
        public final Application getApplication() {
            return mApplication;
        }
        final void attach(...) {
            attachBaseContext(context);
            mApplication = application;
       }
    }
    

    应用程序创建Activity

    private Activity performLaunchActivity(...){
          ContextImpl appContext = createBaseContextForActivity(r);
          Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
    
          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);
    }
    

    4, Service 中的Context

    Service继承ContextWrapper .

    public abstract class Service extends ContextWrapper {
       public final void attach(...) {
            attachBaseContext(context);
            mApplication = application;
        }
        public final Application getApplication() {
            return mApplication;
        }
    }
    

    创建Service

      private void handleCreateService(CreateServiceData data) {
          service = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent);
          ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
          service.attach(context, this, data.info.name, data.token, app,
                        ActivityManager.getService());
          service.onCreate();
      }
    

    5,各种获取Context方法比较

    在Activity 或Service中,都可以使用以下三种方法取得Context, 但无论是Application、Activity或Service中,实际发挥作用的都是baseContext中的 ContextImp对象。

            //获取对象是 当前Activity 或Service 本身,慎用,可能会引起内存泄漏
            Context context = this;
    
            //获取对象是 当前Activity 或Service中的mBase, 即ContextImpl实例
            Context baseContext = getBaseContext();
    
            //以下两种方法获取的都是当前应用的Application对象, 可以放心使用
            Application application = getApplication();
            Context applicationContext = getApplicationContext();
    

    完~

    相关文章

      网友评论

          本文标题:Android 应用启动那些事儿,Application? C

          本文链接:https://www.haomeiwen.com/subject/nzzhrctx.html