Android系列:Application

781 阅读1分钟

谈谈你对Application的理解

1.它的作用是什么

  • 保存应用的全局变量
  • 初始化第三方库

2.它的类继承关系以及生命周期

public class Application extends ContextWrapper implements ComponentCallbacks2 {
    
    
}

public class ContextWrapper extends Context {
    //Application里面实质用的是这个mBase
    Context mBase;
    
    public ContextWrapper(Context base) {
        mBase = base;
    }
    
    /**
     * Set the base context for this ContextWrapper.  All calls will then be
     * delegated to the base context.  Throws
     * IllegalStateException if a base context has already been set.
     * 
     * @param base The new base context for this wrapper.
     */
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }
}

3.它的初始化原理

ActivityThread的main里面调用attach,向AMS打报告,报告自己appthread准备就绪

 private void attach(boolean system) {
            final IActivityManager mgr = ActivityManager.getService();
            try {
            //这里有ipc 
                mgr.attachapplication(mappthread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
    }

到AMS中去找

    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }
    //这里ipc 
     if (app.instr != null) {
                thread.bindApplication(processName, appInfo, providers,
                        app.instr.mClass,
                        profilerInfo, app.instr.mArguments,
                        app.instr.mWatcher,
                        app.instr.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial);

到APP ActivityThread去找,之后经过Handler发送消息回调中:

 private void handleBindApplication(AppBindData data) {
 //获取LoadedApk信息
   final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                    appContext.getClassLoader(), false, true, false);
  final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

            try {
                final ClassLoader cl = instrContext.getClassLoader();
                mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
            } catch (Exception e) {
                throw new RuntimeException(
                    "Unable to instantiate instrumentation "
                    + data.instrumentationName + ": " + e.toString(), e);
            }
            
   app = data.info.makeApplication(data.restrictedBackupMode, null);
   mInstrumentation.callApplicationOnCreate(app);
   
 }
 
    static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }
    
    */ final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }
    
   protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

这里需要注意一点,Application的context是在attachBaseContext回调之后才有的,也就是如果我们在Application的构造函数中去使用context 是会抛异常的,如下

     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference